i-school - 3Dダイビングゲーム 手順6
 以下の内容で順番に実装を進めていきます。

 この手順では、キャラクターをキーボードで移動させるための制御処理を実装していきます。

手順6 −キャラの移動の実装−
 8.スクリプトを使って、キャラの移動を制御する



新しく学習する内容


 ・Header属性
 ・Input.GetAxis メソッド
 ・Vector3.normalized 変数を利用した正規化処理
 ・Rigidbody.velocity 変数と velocity 変数を利用した移動
 ・FixedUpdate メソッド
 ・Rigidbody,freezeRotation 変数


8.スクリプトを使って、キャラの移動を制御する

1.設計


 カメラの制御の際と同じように、キャラのゲームオブジェクトにも専用のスクリプトを作成してアタッチします。
スクリプトを使って、キャラを上下左右(Y軸以外の方向)に移動できるように制御を行います。 

 制御を行うのは、Penguin ゲームオブジェクトにアタッチされている Rigidbody コンポーネントです。
この物理特性の情報をスクリプトを使って操作して、キャラを移動させます。


2.PlayerControoler スクリプトを作成する


 Scripts フォルダの中で右クリックをしてメニューを開き、Create => C# Script を選択してください。
新しいスクリプトが作成されますので、名前を PlayerController に変更します。

 ダブルクリックをしてVisual Studioエディターを起動し、スクリプトを記述してください。


PlayerController.cs

 <= クリックすると開きます。



3.<Input.GetAxisメソッド>


 別の記事で詳しく解説していますので、そちらを確認しておいてください。


 => Input.GetAxisメソッドとInputManagerの関連性


4.<Vector3.normalized 変数を利用した正規化処理>

 
 正規化処理です。magnitude(マグニチュード。長さ)を1としたベクトル(単位ベクトル)を返します。戻り値は Vector3 型になります。

  // 斜め移動の距離が増えないように正規化処理を行い、単位ベクトルとする(方向の情報は持ちつつ、距離による速度差をなくして一定値にする)
    Vector3 direction = new Vector3(x, 0, z).normalized;

 現在のベクトルの方向を維持したまま、magnitudeが1、あるいは0の単位ベクトルを作成することが出来ます。(ベクトルの値が小さいと0になります。)

 この正規化を行うことによって位置の遠近に関わらず、magnitude がすべて 1、あるいは 0 に統一された単位ベクトルの値となるため、
左と下の方向であれば -1右と上の方向であれば 1の値がベクトルとして作成されます。値が 0 に近い場合には 0 がベクトルとして作成されます。

 キー入力が斜め方向になると、縦横直線よりも長い距離が生まれます。その値をそのまま利用してしまうと、斜め移動の方が移動速度が速くなってしまいます。
そこで正規化処理を行い単位ベクトルを作ることで、方向の情報はそのままで、値だけを 0 か 1 か -1 に作り直しています。
この値を移動の入力値として利用することにより、移動方向の情報はそのままで、移動する速度を補正することが出来ています。

Unity公式スクリプト・リファレンス
https://docs.unity3d.com/ja/current/ScriptReferenc...
TechProjin様
UnityのVector3でよく使うものまとめ
https://tech.pjin.jp/blog/2016/02/16/unity_vector3...


5.<Rigidbody.velocity 変数と velocity 変数を利用した移動>


 キャラの移動には色々な方法がありますが、今回は、Rigidbody2D コンポーネントの管理している、Velocity(ベロシティ。速度ベクトル)の情報を操作して、キャラを移動させます。
Rigidbody2D コンポーネントのアタッチされているゲームオブジェクト(今回はキャラ)に対して、速度情報を与えることによって、キャラの移動を行うようにしています。



 velocity(ベロシティ)とはRigidbodyクラスの持つ情報の1つで、各軸(x,y,z)の速度ベクトルを表しています。
ゲームオブジェクトが停止している場合、velocityの値はすべて 0 です。(velocity = 0, 0, 0)

// velocity(速度)に新しい値を代入して移動
rb.velocity = new Vector3(direction.x * moveSpeed, -fallSpeed, direction.z * moveSpeed);

 x軸と z軸については、キー入力の値と moveSpeed 変数の計算結果が入り、その軸の方向へ移動を行います。
y軸は - fallSpeed 変数が指定されていますので、常にマイナス方向への速度入り、その結果、地面に向かって落下を行っています。

 処理の直後に Debug.Logメソッドを入れているので、Console ビューを通じて、この velocity の値の動きを観察することができます。
キー入力を行いながら、どのような処理になっているかを確認しましょう。


参考サイト
Unity公式スクリプトリファレンス
Rigidbody-velocity
https://docs.unity3d.com/ja/current/ScriptReferenc...
SamuraiBlog 様
【Unity入門】Rigidbodyで自在に移動!velocityの活用方法!
https://www.sejuku.net/blog/55084


6.<FixedUpdate メソッド>


 Rigidbody による物理演算の処理を継続的に処理する場合には、Update メソッドではなくて FixedUpdate メソッドを利用して設計を行います。

 FixedUpdate メソッドは初期設定では 0.02秒(1秒間に50回)ごとの固定フレームレートで、物理演算の処理の更新を行う直前に自動的に呼びだされるメソッドです。
Update メソッドはゲームオブジェクト等の動作のレンダリング前毎フレーム呼び出されますので、処理のタイミングとフレームの呼び出しが固定かどうかが、
Update メソッドと FixedUpdate メソッドの違いです。

 以上のことから、FixedUpdate メソッドは物理挙動の更新の直前に呼ばれるメソッドであるため、物理演算の処理を行うことに適していますので
Rigidbody コンポーネントを利用した移動処理については、FixedUpdate メソッドにて行うようにしています。


参考サイト
SamuraiBlog 様
【Unity入門】Updateメソッドとは?FixedUpdateとの違いも徹底解説!
https://www.sejuku.net/blog/49382
かめくめ 様
UnityのUpdateとFixedUpdate、LateUpdateメソッドについて
https://gametukurikata.com/basic/update


7.Penguin ゲームオブジェクトに PlayerController スクリプトをアタッチする


 ヒエラルキーにある Penguin ゲームオブジェクトに PlayerController スクリプトをドラッグアンドドロップしてアタッチしてください。


<手順動画 アタッチ>
https://gyazo.com/8b44e307a627e6d0ee7fce0b8d4cd495


 宣言している変数に Header 属性が付与されているため、インスペクターに情報が追加表示されて変数の内容を理解しやすくなります。


Penguin ゲームオブジェクト インスペクター画像



8.Penguin ゲームオブジェクトの PlayerController スクリプトを設定する


 アタッチした PlayerController スクリプトには、2つの変数の情報が表示されています。
どちらも float 型ですので、順番に値を入力していきます。整数値でも、実行時には浮動小数点として扱われますので問題ありません。
(たとえば、5 と入力した場合、それは自動的に 5.0 として扱われます)


 moveSpped 変数はキャラの上下左右方向への移動速度です。値が大きいほどキャラの移動速度が速くなります。
速すぎても遅すぎてもゲームになりませんので、最初は 10 を設定してください。

 fallSpeed 変数は、キャラの落下速度です。こちらも値が大きいほどキャラの落下速度が速くなります。
最初は 15 に設定しておいてください。


Penguin ゲームオブジェクト 値の設定後のインスペクター画像



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


 設定が終了しましたので、早速ゲームを実行して移動が行えるかどうか、動作を確認します。

 ゲーム実行中に十字矢印キー、あるいはA,S,W,Dキーを押してみてください。そちらの方向にキャラが移動すれば制御成功です。
カメラもしっかりとキャラの移動に対して追従してくれます。


<実行動画>
https://gyazo.com/8fd883be5fb7c8f8a83e75fea8a6667a


10.問題点を修正する


 何回か実行して動作を確認していると気づくことがあるはずです。


<検証動画>
https://gyazo.com/d8a228a5298d256c28bdcec4472d7ad5


 キャラが他のゲームオブジェクトに接触すると、その反動で回転してしまいます。
そういうゲームであれば問題ないのですが、このゲームでは、着水したままの姿勢でいてもらいたいため
これは不具合として解消されるべき問題となります。

 改善策としては、Rigidbody コンポーネントの設定にあります。
このコンポーネントには回転を抑止する Freeze Rotation という機能がありますので、そちらを利用します。
 
 この Freeze Rotation には3つの軸の設定が可能ですので、すべての軸に対してチェックを入れて、機能を有効化してください。
この機能が有効になっている軸は、物理的な接触時には回転しないようになります。


<手順動画> 
https://gyazo.com/209d51413a965499566fcb6a9b6bb2f1


Penguin ゲームオブジェクト インスペクター画像



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


 改めてゲームを実行して確認を行いましょう。地面のゲームオブジェクトに接触して移動しても、キャラの姿勢が変わらなければ制御成功です。


<実行動画>
https://gyazo.com/eb503d9d56b61cca5c77fe4e4c33870d


 以上でこの手順は終了です。

 => 次は 手順7 −着水処理の実装− です。