【Unity2d】移動処理スクリプトの生成:後編

Unity2D

Unity2D ARPG

こんにちは。なおキーヌです。

ブログ毎日更新は337日目になります。

スクリプト整理から始まったのでかなり長くなってしまって申し訳ないです。

私も初めての試みなので調べつつ手探り状態なのでグダグダしてしまうところもあるのですが、
こういった生々しい制作過程を載せられるのもブログの魅力かなと思ってたり。

直ぐに情報が欲しい人には申し訳ないですがご了承ください。

完成したらもう一度1から必要な部分だけを抜き出した記事も作ろうと思ってます。

それでは移動処理を作るための最後の手順をやっていきましょう。

アニメーションナンバー切り替え関数を作る

移動タイプを作る前にまずはアニメーションナンバーを関数を作りましょう。

元々は通常時に上を押されていたら1xにする。

右を押されていたら3xにする。

といった感じに作ってたのですが方向変数を追加したのでもっとシンプルに書けるようになりました。

条件が2回入ってしまうので処理的には恐らく前者の方が軽かったかもしれませんが、
今のPCの性能を考えるとそこまで気にするほどのモノじゃないので見やすさ重視にします。

アニメーション遷移の番号は今更変更も面倒なので既存通りの数値にしておきます(笑)

恐らく今回のゲームは9つもアクション実装しない予定ですので1桁目が9までで事足ります。

アニメーション変更はその数値を見て切り替えを行うだけなので
値がセットされたら一緒にアニメーションを変更しようと思います。

肥大化して来たらアニメーション管理クラスを作ってわけていきましょう。

それではアニメーションナンバーを切り替える関数を作っていきます。

 // 現在の状態
  protected static int _actState = 0;

  // アニメーション変数設定
  protected void setNowAnim(Animator animator) {

    // 通常歩行アニメーションに切り替え
    switch(_actState) {
      // 停止状態
      case 0:
        _switchDirectAnim(0, 10, 20, 30);
        break;
      // 歩行状態
      case 1:
        _switchDirectAnim(1, 11, 21, 31);
        break;
    }
    // アニメーションの設定
    animator.SetInteger("AnimIdx",_nowAnim);
  }

  // 向いてる方向によってアニメーションを決めるスイッチ
  private void _switchDirectAnim(int downAnimNum, int upAnimNum, int leftAnimNum, int rightAnimNum) {
    switch(_direction) {
      case 0:
        _nowAnim = downAnimNum;
        break;
      case 1:
        _nowAnim = upAnimNum;
        break;
      case 2:
        _nowAnim = leftAnimNum;
        break;
      case 3:
        _nowAnim = rightAnimNum;
        break;
      default:
        break;
    }
  }

こういった感じで現状のステートと向いている方向によって、アニメーションをきめていきます。

アニメーション変更の関数は子クラスで該当のキャラクターの所持するアニメーターを取得して渡すので変数は子クラスで定義します。

ステートの決め方

肝心のアニメーションをきめるためのステートですが、
これは基本的には毎フレーム0に戻るようにしておきます。

実行されるまでにキーが押されていたら値を変更するので、
押し続けていれば基本的にはそのアニメーションが固定になります。

とりあえず歩行と停止を完成させるためにステートをきめる処理を作りましょう。

State_Manager.csに以下の関数を追加してください。

  // 押しているキーによってステートを変更
  protected void setState(List<KeyCode> keyList) {
    // とりあえずステートリセット(その場止まり)
    _actState = 0;
    // 移動状態にするかどうか
    if (keyList.Contains(KeyCode.DownArrow) || keyList.Contains(KeyCode.UpArrow) || keyList.Contains(KeyCode.LeftArrow) || keyList.Contains(KeyCode.RightArrow)) {
      _actState = 1;
    }
  }

引数はキーリストを渡します。

そしてまずはステートを0にリセットし、その後に引数に十字キーが含まれているかどうか。

これもっとシンプルにかけないもんですかね……

恐らく定数だと思うのでswitchを使えばもっときれいにかけそうですが
最適化しすぎて可読性が悪くなってしまうと後から見た時何をしているのかわかり辛くなるデメリットもあります。

いい方法が思いつくまではこれでいきましょう。

一旦は移動だけなのでここまででOKです。

何も押されてなかったらステートは0=停止で、十字キーが押されていたら1=歩行中。

優先度が高い行動ほど下に書いていくといった感じですね。

移動中でも掴みキーが押されて居たら掴み状態を優先します。

これらの関数をもとにState_Playerを組んでみましょう。

State_Playerを構築

後はマネージャー側で用意した関数に必要な値を渡してUpdateで回すだけですね。

プレイヤーのアニメーターを取得するためにタグを付けてオブジェクトを取得して、
アニメーターを確保する仕組みも作りました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

public class State_Player : State_Manager
{
  // コントローラープレイヤースクリプト
  private Controller_Player _cm;

  // プレイヤーアニメーションコンポーネント
  private Animator _animator;

  protected override void Start() {
      _cm = GameObject.FindGameObjectsWithTag("Controller_Manager")[0].GetComponent<Controller_Player>();
      _animator = GameObject.FindGameObjectsWithTag("Player")[0].GetComponent<Animator>();
  }


  protected override void Update() {
    // 十字キーが一つでも格納されてたら稼働
    if (_cm.PushedArrowKeyList.Count > 0) { setDirection(_cm.PushedArrowKeyList[0]); }
    // ステートをセットする
    setState(_cm.PushedKeyList);
    // 向きとステートを元にアニメーションを設定
    setNowAnim(_animator);
  }
}

これで十字キーを押したらアニメーションしてくれるようになりました。

後は実際の移動処理を作るだけですね!

ここまで長かった……

移動タイプは次回辺りに実装してみようと思いますのでとりあえずドット移動までやりましょう。

Move_Managerに機能追加

やっとこさ前編に用意したMove_Managerを弄る時が来ました。

別に最初に書かずにここに書いたら良かったですね(笑)

基本的にvirtualで実装しているので子クラス側で色々実装します。

Move_Managerを継承した子クラス「Move_Player」を作りましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Move_Player : Move_Manager
{
    // プレイヤーオブジェクト
    private GameObject _Player;
    // プレイヤーステートスクリプトの取得
    private State_Player _State;

    private float _speed = 30;

    // 更新処理
    protected override void Start() {
        // プレイヤーオブジェクトの取得
        _Player = GameObject.FindGameObjectsWithTag("Player")[0];
        _State = GameObject.FindGameObjectsWithTag("State_Manager")[0].GetComponent<State_Player>();
    }
    protected override void Update() {
        dotMove();
    }

    // ドット移動関数
    protected override void dotMove() {
        float vx = 0;
        float vy = 0;

        if (_State.ActState == 1) {
            switch(_State.Direction) {
                case 0:
                    vy = -_speed;
                    break;
                case 1:
                    vy = _speed;
                    break;
                case 2:
                    vx = -_speed;
                    break;
                case 3:
                    vx = _speed;
                    break;
                default:
                    break;
            }
        }
        // 実際のドット移動
        _Player.transform.GetComponent<Rigidbody2D>().velocity = new Vector2(vx, vy);
    }

    // グリッド移動関数
    protected override void gridMove() {
    }

}

これをアタッチするためのMove_Managerを作りましょう。

やっていることはプレイヤーオブジェクトとステートオブジェクトのスクリプトの取得からはじめ、
それらの情報を元にどう移動するかを決め、最後に移動させるといった仕組みです。

まだ上下左右しか動かせないので次回は斜め移動も実装しつつグリッド移動も実装してみましょう。

それでは。