ゴマちゃんフロンティア

気まぐれと勢いで作るUnityゲーム開発日記です。

【開発メモ】攻撃後の回避アクションの実装

time 2015/10/18

というわけで、今回のお題はこれです!

20150605_1

攻撃後の隙や硬直を回避行動でキャンセルできる機能の実装になります!
今日のアクションゲームにはほとんど搭載されているものですね。
こういった基本的な機能は思いついた時に実装してしまいたいところです。
既に回避という名目で「短距離をダッシュする」というアクションがあるので、これに機能を上乗せする感じになります。

どうでもいいですが、GIFアニメーションを撮るのがかなり下手です。
撮ったものを編集したりするソフトがあれば良いですが・・・現状ではベタ貼り状態ですorz

攻撃中の移動制限

そもそも現状では攻撃中でもヌルヌル動けてしまうので、まずはそこから修正。
PlayerクラスのUpdate内に以下の処理を加えます。

void Update() {
    stateInfo = animator.GetCurrentAnimatorStateInfo(0);

    if (stateInfo.IsTag("Attack")) {
        isAttack = true;
        charMotor.canControl = false;
    } else {
        isAttack = false;
        charMotor.canControl = true;
    }
}

AnimatorControllerの攻撃系ステートにタグをつけ、PlayerクラスのUpdate内で攻撃中か判定します。
攻撃モーション中であればCharacterMotorのcanControlをfalseに設定。
攻撃する方向は動かせるようにしたいので、PlatformInputControllerはそのままにしておきます。

isAttackはPlayerクラスのフィールドに持たせ、stateInfoから判定して設定しています。
キャラが攻撃中かどうか判定できるようになり、他の機能を実装する際に便利です。

回避方向の制御

当たり前ですが、一方向にだけ回避できてもあまり意味がないですね。
3Dアクションである以上、移動キーを入れた方向にクルッと回避して欲しいところです。

void Update() {
    // 回避ボタン入力時
    if(Input.GetMouseButtonDown(2) || Input.GetButtonDown("Dash")){
        if (isAttack) {
            // 攻撃モーション中の回避可能タイミングを制御
            if (GameConstants.ATTACK_CANCEL_TIME < animator.GetCurrentAnimatorStateInfo(0).normalizedTime) {
                Vector3 inputDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

                // 入力が行われた場合、入力方向に振り向かせる
                if (inputDirection != Vector3.zero) {
                    transform.rotation = (inputDirection);
                }
                iTween.ValueTo(gameObject, iTween.Hash(
                    "from", transform.forward,
                    "to", Vector3.zero,
                    "onupdate", "Thrust",
                    "time", 1.0f,
                    "easetype", "easeOutQuart")
                );
            }
        }
    }
}

protected void Thrust(Vector3 v) {
    charControl.Move(v * Time.deltaTime * 100);
}

とりあえず入力した方向に前転するようにしました!
MoveByでtransform.forwardを指定しても上手くいかないので、Value.ToのonupdateでCharacterControllerのMoveを実行するようにしています。

Moveで移動させるわけですが、PlatformInputControllerの「入力方向に振り向く」という処理が入り、思うように移動させることができません。
なので、キー入力された方向に瞬時に振り向き、その状態で前方に移動させるようにしました!
移動キーを入力した方向をVector3型のx、z軸に設定しておき、Quaternion.LookRotationで振り向かせます。
もし入力がない場合=零ベクトルの場合は振り向かないように制御することで、キャラクターを前方に移動させることができます。

ちなみにonupdate内の関数でtransform.positionを直接加減する方法もあります。
ただし移動時に判定を考慮しないため、壁やブロックをぶち抜いて移動してしまいます。
ということで、アクションゲームには不向きな方法かと思われます。

回避可能なタイミングの制御

攻撃モーションの全タイミングでキャンセルを受け付けるのは流石にまずいので、特定のタイミングのみ受け付けるようにします。
一般的なゲームと同じく、攻撃モーションの後半ぐらいからでいいでしょう。
モーション毎に設定できるのが理想ですが、自分のスクリプト構成では面倒そうだったので、とりあえず固定値でいきます。

上で記載したスクリプトの5行目付近のif文が該当します。
AnimatorStateInfo.normalizedTimeで現在のステートの実行時間が割合として取得できます。
ステートが半分再生された場合は0.5、全て再生された場合は1.0といった感じです。
なので「モーションの後半からのみ入力を受け付けたい!」という場合、normalizedTimeが0.5より大きいかを判定すればOKです。

固定値を直に書くのはよろしくないので、GameConstantsという定数用クラスに「ATTACK_CANCEL_TIME」を定義し、そこに0.5fを設定しました。
定数を扱う方法については以下の記事をご参照ください。

【再編集】Unity開発メモまとめ (その他)

まとめ

そんなわけで、攻撃後の回避アクションを実装してみました!
慣れた人ほど硬直はもどかしく感じるもので、プレイヤーの介入で快適になる要素はなるべく入れていきたいところ。
キャンセルできすぎても問題なので、その加減が重要でもありますね。

2015/11/15 追記

上記実装では、カメラのY軸の角度が変化した際に変な方向を向いてしまいます。
どの角度からでも入力方向を振り向くようにするため、スクリプトに修正を加えました。
7行目のinputDirectionの算出時にカメラの向きを考慮します。

GameObject mainCamera = GameObject.FindGameObjectWithTag("MainCmaera") as GameObject;

Vector3 forward = mainCamera.transform.TransformDirection(Vector3.forward);
Vector3 right =mainCamera.transform.TransformDirection(Vector3.right);
Vector3 inputDirection = Input.GetAxis("Horizontal") * right + Input.GetAxis("Vertical") * forward;

「Vector3.forwardって何よ」と思いきや、単純に (0, 0, 1) のベクトルを表すだけのものみたいです。
TransformDirectionでカメラの正面をワールド座標に変換して掛ける・・・難しいですね。
まだまだAPIの理解が足りていないようですorz

実際には毎回カメラの参照を取るのはアレなので、Startあたりで取得してフィールドに持つ方が良いと思います。
他の箇所でも使う場合はなおさらですね。

本修正にあたり、こちらのサイトを参考にさせて頂きました!
http://nokutanno.kagome-kagome.com/unity/-unity-%E3%82%AB%E3%83%A1%E3%83%A9%E6%96%B9%E5%90%91%E3%81%AB%E3%82%88%E3%81%A3%E3%81%A6%E5%89%8D%E6%96%B9%E5%90%91%E3%82%92%E6%B1%BA%E3%82%81%E3%82%8B

スポンサーリンク

down

コメントする



ツイッター