i-school - ベルトスクロールアクション プレイヤーの移動
 ベルトスクロールアクションでは、移動の要素が特徴的です。

 ・奥行方向への移動時にはキャラの向きが変わらない
 ・エリア内での移動範囲に制限がある(ベルトスクロール)

 ここでは向きを変えずに奥行移動をする際に向きを変えずに移動する処理と、移動範囲の制限処理を実装します。



設計


 3D空間での移動になるため、X軸で左右移動を、Z軸で奥行移動を行うようにします。

 このとき移動に合わせて全方位にキャラの向きを変えてしまうと奥行移動をした際に、キャラが正面を向いてしまったり、背中を見せてしまったりします。
このままでも問題はありませんが、ベルトスクロールアクションというゲーム性に合わせて、キャラの向きは左右方向のみ固定をしたい所です。

 キャラの移動時に向きに関する制御を行うことでこの問題を解消することが出来ます。


 キャラの移動範囲ですが、ベルトスクロールアクションにはその名の通り、エリア単位での移動範囲に制限があります。
そしてそのエリアの敵を全滅させることで次のエリアへの移動が可能になります。

 この部分もキャラの移動の部分に制御を行うことでロジックを考えます。

 移動範囲は固定値にせず、各エリアごとに移動できる範囲の情報を持たせることができれば制御が可能です。

 まずは制限ができるかどうかから検証していって、その後、実際にエリアの移動範囲を反映していく手順で実装していきます。


実装動画 上下移動では向きを変えない
https://gyazo.com/d2f497e5fb3b6ef5b6629c0fb146f1f5

実装動画 画面の左右には移動制限がある
https://gyazo.com/5053e9bfca1585283e2035df5885cf91


実装の手順


 1.移動制限用のクラスを作成する
 2.キャラを管理するPlayerControllerクラスを作成する


新しく学習する内容


 1.MonoBehaviourクラスを継承しないクラスの作成、入れ子クラスの作成
 2.Mathf.Clampメソッド
 3.const修飾子


1.移動制限用のクラスを作成する


 今度の設計をふまえて、移動制限用のクラスを作成しておきます。


MoveLimit.cs



<MonoBehaviourクラスを継承しないクラスの作成、入れ子クラスの作成>


 MonoBehaviourの継承がありませんので、ゲームオブジェクトにアタッチすることはできませんが
いずれのスクリプトからでもインスタンスして利用することが出来ます。

 またクラスの中にクラスがあります。このような作りのクラスを入れ子(ネスト)クラスと言います。
1つのファイルとして用意する必要のない、使用範囲の限られているクラスなどは、このように入れ子クラスにして使うことが出来ます。

 今回はHorizontalLimitクラスとDepthLimitクラスを入れ子クラスとして作成しています。
これはMoveLimitクラス内に用意して、まとめて使うことを想定した設計になっています。

 
 また各クラスには[Serializable]属性が付与されています。この属性を付与すると、このクラスをインスペクターで確認出来るようになります。


2.キャラを管理するPlayerControllerクラスを作成する


 PlayerControllerクラスを作成し、キャラクターにアタッチします。

PlayerController.cs



<Mathf.Clampメソッド>


 Mathf 構造体は、Unity が用意している、数学関数の変数やメソッドをまとめてある構造体です。
通常の Math クラスと異なり、戻り値は float 型で用意されています。


参考サイト
Unity 公式スクリプト・リファレンス
Mathf



 Clamp メソッドは、「制御したい指定値を、指定した範囲内の最小値、最大値に収めてくれる(置き換えてくれる)」処理になります。

<メソッドの記法>
  制御したい指定値 = Mathf.Clamp(制御したい指定値, 最小値, 最大値);
 
 このメソッドを利用して、計算処理後の値を制限することが出来ます。

 そのため、下記の処理は、transform.position.xの値を、
moveLimit.horizontalLimit.left 〜 moveLimit.horizontalLimit.rightの間に制限するという処理になります。
もしも最小値と最大値を超えた場合には、自動的にその範囲内に収まるように調整してくれます。

 float posX = Mathf.Clamp(transform.position.x, moveLimit.horizontalLimit.left, moveLimit.horizontalLimit.right);


 その結果、常にプレイヤーのゲームオブジェクトの移動範囲を、制限された範囲内に収まるよう制御することが出来ます。


参考サイト
Unity 公式スクリプトリファレンス
Mathf.Clamp


<const修飾子>


 変数の宣言と一緒につけることができる修飾子です。この修飾子を持つ変数は固定値となり、変更することが出来なくなります。
そのため、ゲーム中で常に固定値として利用したい値を用意する場合に利用すると便利です。

 今回はString型の値を用意し、何回か書く文字列の打ち間違えを未然に防ぐようにしています。

 private const string HORIZONTAL = "Horizontal";


ゲームを実行して動作を確認する


 PlayerControllerクラスをプレイヤーキャラクター役のゲームオブジェクトにアタッチするとインスペクターにアサイン情報が表示されます。

 移動速度と回転速度は適宜な値を設定してください。




 [Serializable]属性を持つクラスであるため、MoveLimit変数を宣言すると、インスペクターに表示することが出来ます。
ここでキャラの移動範囲を仮に設定してみてください。




 その後、ゲームを実行してみましょう。
先ほど指定した移動範囲内しかキャラが移動が出来なくなっていれば成功です。