i-school - 2DタイルマップRPG 手順5
 この手順では、プレイヤーとなるキャラをゲーム画面に配置して設定を行います。

 以下の内容で順番に実装を進めていきます。

手順5 ープレイヤーキャラの作成ー
 8.プレイヤーキャラ用のゲームオブジェクトを作成する
 9.PlayerController スクリプトを作成し、プレイヤーキャラを移動させる



 新しい学習内容は、以下の通りです。

 ・RequireComponent 属性
 ・Header 属性 
  ・Input.GetAxis メソッド
 ・Vector3.normalized 変数を利用した正規化処理
 ・Rigidbody2D.velocity 変数と velocity 変数を利用した移動処理
 ・FixedUpdate メソッド
 ・Summary(サマリー)機能 
 ・InputManagerによるキー入力の設定



8.プレイヤーキャラ用のゲームオブジェクトを作成する

1.設計


 プレイヤーの分身となって操作を行うためのキャラを製作していきます。


2.Unity にキャラの画像をインポートする


 プレイヤーとして使用したいキャラの画像ファイルを Unity へインポートしてください。
地形の画像ファイルをダウンロードした、ぴぽや様にはキャラの画像ファイルも用意されています。
ぴぽや様
ホーム
https://pipoya.net/sozai/

 インポートの手順や、画像ファイルの分割の手順なども同じです。
前回の手順を参考にしながら作業してください。


フォルダ画像(参考例)




3.ヒエラルキーにキャラを設置する


 画像のフォルダ内にある同じ方向を向いている画像ファイルをまとめて選択します(3〜4ファイル)
まとめて選択する方法は Ctrl キーを押しながら左クリックです。
どの方向を向いている画像ファイルでも構いません。今回は正面を向いている画像ファイルを3つ選択しています。


画像ファイルの選択



選択時のインスペクター画像



 選択したファイルをそのままヒエラルキーにドラッグアンドドロップします。
Create New Animation というウインドウが開きます。


Create New Animation ウインドウ



 Create New Animationウインドウは、作成複数の画像ファイルをヒエラルキーにドラッグアンドドロップすると表示されるウインドウです。
それらの画像を使ったアニメーションを再生する、アニメーションクリップを自動的に作成してくれます。
(複数枚の画像をパラパラ漫画のようにつなぎ合わせて1つのアニメにしています。)

 ファイル名を player_front.anim に変更して保存を選択してください。正面以外のアニメの場合には、その方向の名称にしてください。
保存先には Animations のようなフォルダを作成しておいて、その中に保存するようにすると管理しやすくなります。

 ヒエラルキーに画像ファイルの最初のファイル名と同じ名称のゲームオブジェクトが作成されます。
(複数の画像の場合、自動的に先頭のファイル名を持つゲームオブジェクトになります)


ヒエラルキー画像



 そのままゲームを実行してみてください。キャラがアニメーションを繰り返すはずです。(キャラの位置はどこでも構いません。)


<実行動画>
動画ファイルへのリンク


 このままですと、キャラが地形のタイルに隠れて見えない状態になってしまうため、
描画する優先順位を設定します。


4.Player ゲームオブジェクトの設定を行う


 ヒエラルキーのキャラのゲームオブジェクトを選択し、名前を Player に変更してください。

 Player ゲームオブジェクトの Transform コンポーネントの Position の情報が (0, 0, 0) ではない場合には、(0, 0, 0) に設定してください。

 最後に、Sprite Renderer コンポーネントの Additional Settings 内にある Sorting Layer を選択し
Default を Chara に変更してください。Chara が最も優先順位が高い Sorting Layer の種類であるため、
ゲーム画面での描画の順位が変わり、Player ゲームオブジェクトが他のタイルのゲームオブジェクトよりも常に手前に表示されるようになります。


インスペクター画像

 

Sceneビュー画像



Game ビュー画像



 次は、プレイヤーキャラの移動の制御処理を作成します。


9.PlayerController スクリプトを作成し、プレイヤーキャラを移動させる

1.設計


 Unity においてゲームオブジェクトの操作を行うためには、スクリプトを利用して、制御が必要なコンポーネントの情報にアクセスして制御操作を行います

 今回制御を行いたいのは Player ゲームオブジェクトになります。そのため、このゲームオブジェクト専用のスクリプトを作成します。



 新しく PlayerController というスクリプトを作成し、このスクリプトを使ってキャラの制御を行っていきます。

 制御とは、キャラの行動(移動、ジャンプなど)だけではなく、移動に合わせたアニメーションの再生や、画面の移動範囲の制限など多岐に渡ります
それらを順番に実装していきながら、スクリプトの学習を行います。


 この手順では、キャラの移動について扱います。移動には Rigidbody2D コンポーネントの機能を利用します

参考サイト
Unityインターハイブログ様
物理エンジンと当たり判定を使いこなそう(その1)
http://inter-high-blog.unity3d.jp/2019/06/28/rigid...



 最初はキーボードで操作ができるようするため、キーボードのキー入力に反応して、ゲーム画面のキャラが移動するように制御を追加します
移動用のアニメーションの制御については、次回以降に行います。

 スクリプトを作成し、修正していくポイントは、すべてを一度に記述しない、ということです。
1つ1つ、出来る事、理解している処理を積み上げて、その結果として、複雑かつ多様な処理が出来上がるようにします。


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


 Project 内で右クリックをしてメニューを開き、Create => Folder を選択し、Scripts フォルダを作成します。

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

 名前を PlayerController に変更します。ダブルクリックしてエディター(Visual Studio)を立ち上げ、スクリプトを書いていきます。

 スクリプトを作成したら必ずセーブをします。VisualStudio では ctrl + Shift + S キーで一括セーブできます。


PlayerController.cs

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



3.<RequireComponent(typeof(クラス名/コンポーネント名))]属性>

  
 [] で書かれた情報は属性(Attribute)と呼ばれるものです。
属性を付与する事で他の変数と区別したり、特別な挙動を設定することが出来ます。

[RequireComponent(typeof(Rigidbody2D))]
public class PlayerController : MonoBehaviour {

 このRequireComponent(リクワイア・コンポーネント)属性は、クラス名の1行上に記述する属性です。

 この属性の(引数)で指定したクラスやコンポーネントが、このスクリプトがアタッチされているゲームオブジェクトにアタッチされていないと、Console ビューにエラーが出るようになります。 

 またこの属性が定義されているスクリプトをゲームオブジェクトにアタッチすると、引数で指定しているコンポーネントが自動的にアタッチされます。(今回は Rigidbody2D コンポーネント)
つまりこの機能は、スクリプトを正常に動作させるために必要なコンポーネントを強制的に用意してくれる内容になっています。
 
 今回この PlayerController スクリプトにより Player ゲームオブジェクトを移動させるには Rigidbody2D コンポーネントが必要になります。
[RequireComponent(typeof(Rigidbody2D))]属性を追加することによって、自動的にコンポーネントのアタッチを行うとともに、アタッチされていない場合にはエラーが出るようにしています。


4.<Header属性>


 Header(ヘッダー)属性は、先ほど学習した RequireComponent 属性と同じ、属性の1つです。
 Header 属性を変数の宣言に追加すると、インスペクター上に( )内に記述した文字が表示されます。

    [Header("移動速度")]
    public float moveSpeed;

あるいは

    [Header("移動速度")] public float moveSpeed;

 記述の方法はどちらでも構いません。


インスペクター画像(変数名の上に Header 属性で設定した内容が表示されている)



 インスペクター上に表示される変数名だけですとわかりにくい場合がありますが、日本語でコメントを付けることができるため、変数の内容がわかりやすくなります。
今後も特に教材内に記載がなくても、自分で判断をして、必要に応じてこの Header 属性を使いこなしましょう


参考サイト
エクスプラボ 様
【Unity】HeaderAttributeを使ってフィールドを整理してみなイカ?
https://ekulabo.com/attribute-header


5.<Input.GetAxis メソッド>


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


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


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

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

  // 斜め移動の距離が増えないように正規化処理を行い、単位ベクトルとする(方向の情報は持ちつつ、距離による速度差をなくして一定値にする)
    Vector3 dir = new Vector3(horizontal, vertical, 0).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...


7.<Rigidbody2D.velocity 変数と velocity 変数を利用した移動>


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



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

  // velocity(速度)に新しい値を代入して移動
  rb.velocity = dir * moveSpeed;

 x軸と z軸については、dir 変数で準備したキー入力の値が代入されています。この値と moveSpeed 変数の計算結果が入り、その軸の方向へ移動を行います。

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


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


8.<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


9.<Summary(サマリー)機能>


 関数(メソッド)やクラスを作成し終わりましたら、必ずその関数やクラスの説明を書くように心がけましょう。書く場所は関数名、あるいはクラス名の1行上の部分です。
半角スラッシュを3個連続で記述すると説明用のコメントであるサマリー(概要)が自動的に記述されます。

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


 => 知っておきたい豆知識


10.Player ゲームオブジェクトに PlayerController スクリプトをアタッチし、設定を行う


 ヒエラルキーの Player ゲームオブジェクトに PlayerController スクリプトをドラッグアンドドロップしてアタッチします。
アタッチしたら、必ず、ゲームオブジェクトのインスペクターの確認を行い、正常にアタッチされているかを確認してください。

 PlayerController スクリプトに合わせて、Rigidbody2D コンポーネントも同時にアタッチされています。
これは PlayerController スクリプトに設定してある RequireComponent 属性による機能です。



 Player ゲームオブジェクトの設定を行います。設定するコンポーネントは2つです。

 最初に Rigidbody2D コンポーネントの設定を行います。

 Gravity Scale の値を 0 に変更してください。0 にすることにより、重力の影響を受けなくなります。
 
 Constraints プロパティ内の Freeze Rotation の Z にチェックをいれてください
Rigidbody2D コンポーネントを利用して移動を行う場合、座標を直接変更するのではなく、物理演算を利用して、その結果としてキャラの座標が移動します。
そのため、重力や摩擦といった物理法則が移動の際に関わってくることになります。他のものにぶつかれば停止しますが、その時に加速があれば、回転が発生して前のめりに倒れます。
この設定により、キャラが移動したり、停止したりした際に、加速による勢いがあっても回転を起こさなり、倒れなくなります。


Player ゲームオブジェクト Rigidbody2D コンポーネント




 続いて、PlayerController スクリプトの中で public 修飾子で宣言している変数がインスペクター上に表示されますので、適宜な値を代入してください。


Player ゲームオブジェクト インスペクター



 以上で設定は完了です。


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


 スクリプト内の制御処理について、しっかりと理解をした上で、ゲームを実行して処理を確認しましょう。

<実装動画>
動画ファイルへのリンク



12.<InputManagerによるキー入力の設定>


 Unityには InputManager という設定項目があり、この中に最初から特定のキー入力用のキーボードのボタンを登録してあります。

 InputManagerは、Unityの左上のメニューにある Edit => Project Settings からProject Settings ウインドウを開き、左の項目から InputManager を選択すると確認と設定が可能です。

 今回は設定をそのまま利用します。項目にある、Horizontal を選択してください。下記のような設定用の内容が表示されます。


InputManager


 一番上の設定項目に Name があります。この部分に指定した文字列を命令することによって、キー入力用の判定を行うことが出来ます。
Horizontal には始めから Horizontal という文字列が登録されていますので、この情報を利用してキー入力用の判定を行う処理をスクリプトに記述します

 実際に、どのキーの入力を判定するかですが、この Horizontal には、Negative Button に left(左矢印キー)、
Positive Button にright(右矢印キー)が登録されていますので、水平(横)方向用のキー入力の判定を取得することが出来るようになっています。

 Vertical についても同様です。あわせて確認しておきましょう。



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

 次は 手順6 −プレイヤーキャラの移動アニメの作成− です。