【開発メモ】アクション「走り移動」の実装

というわけで、仕事の納期間近で忙しいりべるんです。
ブログも前回からかなり間が空いてしまっています。
今やっている「敵キャラクターのロジック修正」が結構ガッツリな感じなので、仕事が落ち着くまではちょっとしたことを主題にしていこうと思います!

shot2ss20160301210901495

今回実装するのは「走り移動」です。
通常の歩き移動より早く移動できるアレです。

実は既に「短距離を高速移動する」というアクションがあり、それをダッシュ扱いにしていたりします。
挙動としてはロックマンXシリーズのダッシュに近いです。
更に攻撃後の硬直などにダッシュボタンを押した場合はローリングになります。
こちらの挙動は他の3Dゲームでいうステップに近いです。

似たようなアクションが多くなりますが、行動の選択肢は増やしていきたいので実装します。
ある程度移動アクションがあればゲーム面で不便に感じることはない・・・はず。

基本的な仕様

ダッシュボタンを押しっぱなしにすることでダッシュから派生します。
攻撃後のローリングからは派生しません。
移動入力している間は通常移動より早く移動できます。

一定時間移動を行うと自動的に走り出すゲームもありますね。
これを取り入れるかは難しいところです。
専門学校の卒研で作ったゲームには搭載しましたが、「一定時間」が短すぎると暴発してしまうことが多く、また長すぎるとそもそも入れる意味がありません。
結局提出時にはボタン長押しでの派生のみになりました。
今回はとりあえず搭載し、ゲームが出来てきてから様子を見ることにします。

モーションとスクリプトの作成

それっぽい名前で「Dash」が良かったのですが、既にダッシュ用にモーションを作ってしまっているので、素直に「Run」で作ります。

shot2ss20160301211038807

リアルな人間キャラならともかく、2~3等身のキャラの走りモーションなんて似たようなものです。
キャラの性格・設定に合わせて作るのがベストですが、そんな余裕はないので適当にします!
Unityへインポートする際はループさせるように設定します。

shot2ss20160301211118902

続いてAnimatorController上から制御します。
パラメータ「Run」「Move」を作成し、DashステートとMoveステートからの遷移を設定します。

1つは「ダッシュ後に派生」なので、Dash ステートにスクリプトを付け、そこでダッシュボタンが押下されている状態であれば遷移させます。

【Dashクラス】

using UnityEngine;
using System.Collections;

namespace StateController.PlayerAnimator {

    public class Dash : StateMachineBehaviour {

        public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
            if (Input.GetButton("Dash")) {
                animator.SetBool("Run", true);
                animator.Play("Run");
            }
        }
    }
}

「OnStateExit」はモーション終了時に呼び出されるので、そこでダッシュボタンが押下されているか判定します。
パラメータ「Run」のtrue/falseで走り状態の持続を制御します。

もう1つの条件は「一定時間移動」です。
何を持って「一定時間移動したか」を判別するのがシビアなところですね。
単にキー入力だけで判定すると、その場でぐるぐる回っていても派生してしまいます。
ということで、判定には CharacterMotor の magnitude の値を使用します。

PlayerクラスのUpdate()内に以下の処理を追加します。

【Playerクラス】

moveSpeed = charMotor.GetDirection().magnitude;

// 移動速度をAnimatorにセット
animator.SetFloat("Move", moveSpeed);

// 一定時間移動で走り移動へ遷移
if (0.5f < moveSpeed && charMotor.IsGrounded()) {
    runCount += 1;
    if (GameConstants.AUTO_RUN_TIME < runCount) {
        motionChange("Run", true);
        runCount = 0;
    }
}

最後に走っている際の移動速度を変化させます。
Run ステートにスクリプトを付け、CharacterMotor の「MaxForwardSpeed」の値を切り替えます。

【Runクラス】

using UnityEngine;
using System.Collections;

namespace StateController.PlayerAnimator {

    public class Run : StateMachineBehaviour {

        public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
            animator.gameObject.GetComponent<Player>().getCharacterMotor().movement.maxForwardSpeed = GameConstants.DASH_MOVE_SPEED;
        }

        public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
            if (animator.GetFloat("Move") <= 0) {
                animator.SetBool("Run", false);
            }
        }

        public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
            animator.gameObject.GetComponent<Player>().getCharacterMotor().movement.maxForwardSpeed = GameConstants.DEFAULT_MOVE_SPEED;
        }
    }
}

速度を変える処理が横に長い!
現状では「Playerの参照を取っておく」といったことができない(と思われる)ため、いちいちGetComponent()する必要があります。
PlayerクラスからAnimator関連の処理を抜き出せるのはメリットですが、やや使いにくい感じがします。

「GameConstants~」系はただの定数なのでお好みで。
MoveパラメータにはPlayerクラスからセットされた magnitude が入っているので、これで走り状態の維持するかの判定します。

まとめ

・「ダッシュ」「ローリング」に加えて「走り移動」を実装
・ダッシュ後にボタン長押しか一定時間移動で派生
・移動キーが押されていない場合に通常移動に戻す

ちょっとした機能でも実際作るとガッツリだったりします。
Animatorとかスクリプトとか絡んでくると大抵こうなってしまいます。
次回はもうちょっと簡単な話題にするかもしれません。
「ジャンプと組み合わせて使えば遠くまで飛べる」とか欲しいですね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*