Unityに関連する記事です

 プレイヤーの移動機能を実装します。
新しく学習する内容が非常に多いため、1つずつ、理解しながら進めていくようにしてください。

 プログラムは、事前に用意されている機能を活用し、それを上手く組み立てることでロジックを作ることが出来ます。
よって1つ1つの機能が理解できていないと、処理全体を読み解けなくなりますし、自分でロジックを作ることも難しくなります。

 ゆっくりと学習し、必要であれば復習をおこなってください。



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

手順5 ープレイヤーの移動機能の実装ー



 ・RequireComponent(typeof(クラス名/コンポーネント名))]属性
 ・SerializeField 属性
 ・TryGetComponent メソッドと out キーワード宣言
 ・Input.GetAxis メソッド
 ・FixedUpdate メソッド
 ・Rigidbody.velocity 変数と velocity 変数を利用した移動
 ・Summary(サマリー)機能

 ・Rigidbody.velocity.normalized 変数
 ・Vector3.zero 変数
 ・Quaternion.LookRotation メソッド
 ・学習のための工夫



1.プレイヤー用のゲームオブジェクトの移動機能を実装する

1.設計


 3D空間におけるプレイヤーの移動については、前後左右方向の移動を行う形の実装を行います。
上下方向(Y軸)の移動は主にジャンプや落下なりますので、それ別途の違う手順で方法を説明します。

 まずは最初にプレイヤーの分身となる3Dキャラクターのゲームオブジェクトをゲーム画面に配置します。
その後、移動用のスクリプトを作成して、プレイヤーの移動を実装します。

 なお、この移動方法は基本的な移動方法です。目的である白猫プロジェクトのようなゲームにおける移動の場合には、
ゲーム内のカメラのアングルも加味した上でプレイヤーを移動させる必要があります。

 よって、まずはこの手順で基本的な移動方法を学習し、カメラの機能を学習してから、新しい移動方法を学習していく流れで進めます。


2.PlayerMove クラスを作成する


 プレイヤーの情報を管理するためのスクリプトとして PlayerMove クラスを作成します。
このスクリプト内に移動の処理を記述し、プレイヤーを制御します。

 スクリプトを作成していく際には、先々のことを考えて、事前にフォルダを作成し、その中にスクリプトを作成していくことをお勧めします。

 Assets フォルダ内で右クリックをしてメニューを開くと、Create => Folder というコマンドがありますので、そちらで新しいフォルダを作成できます。
Scripts のようなわかりやすいでフォルダを作成し、そのフォルダの中で再度右クリックをしてメニューを開き、Create => C# Script を選択して
スクリプトを作成し、名前を PlayerMove に変更してください。


フォルダ作成




PlayerMove.cs

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



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

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

[RequireComponent(typeof(Rigidbody))]
public class PlayerMove : MonoBehaviour {

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

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

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


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


4.<SerializeField 属性>


 変数の宣言に合わせて宣言できる、属性情報と呼ばれるものの1つです。変数の宣言の前に [ ] 付きで書かれた内容が属性情報となります。

 今回利用している属性は SerializeField という属性情報です。この機能は、インスペクター上に変数を表示させる、というものです。

 主に private 修飾子とセットで用いられ、アサインをインスペクター上で可能にするものの、変数の参照先が外部のスクリプトにない(publicの必要がない)場合に利用します。

 たとえば ButtonコンポーネントやTextコンポーネントといった、アサインはするものの、その変数の利用先が他のスクリプトにはないようなもの、には利用しやすいです。

 今回はプレイヤーの移動速度を設定するための変数の宣言に属性情報を付与しています。
移動速度の情報をインスペクターに表示させることにより、移動速度の調整にあたり、
スクリプト内でその都度書き直さなくてもよいようにする目的で利用しています。


5.<TryGetComponent メソッドと out キーワード宣言>


 Unity2019.2以降に追加されたメソッドです。処理結果として bool 型で戻り値を返してくれます。
このときの処理結果というのは、指定したコンポーネントの型の取得を行い、それが取得できればtrue、取得できなければfalseが戻ります

 また out キーワードによる宣言があります。
 out キーワード宣言を行うと、out を付けた引数で指定した変数はメソッド内で必ず結果が入ることが保証されるものです。
そのため、処理結果の戻り値が true の場合には必ず、この out の後に宣言した変数内に型が代入されます

 端的にいうならば、GetComponent メソッドの処理に加えて、その処理の成否判定(コンポーネントが取得出来たか、出来なかったか)を同時に行ってくれるメソッドになります。

<実装例 
  private Rigidbody rb;

  TryGetComponent(out rb);

<実装例◆〔瓩蠱佑魍萢僉
if(col.gameObject.TryGetComponent(out Rigidbody rigid)) {

   // 処理を書く
}

 今回は実装例,僚萢として利用しています。スクリプト内に TryGetComponent メソッドを直接記述した場合、GetComponent メソッドと同様に、
このスクリプトがアタッチしているゲームオブジェクトのコンポーネントから指定されている種類のコンポーネントを取得してます。
それを out キーワード後の rb 変数に代入しています。GetComponent メソッドのように<型引数>を指定していないのは、rb 変数によって型を推論することが可能であるためです。

 out キーワード以降にはゲームオブジェクトから取得したい型と変数を宣言します。今回のように事前に変数の宣言をしている場合には、変数のみを用意しておくことが出来ます。

 実装例△両豺腓蓮△發靴發海 TryGetComponent メソッドの処理結果が実行可能ならば、つまり、ゲームオブジェクトに Rigidbody コンポーネントがアタッチされているのであれば、
out として用意した rigid 変数に Rigidbody コンポーネントの情報が代入されます''。また、true の値が、それとは別に処理結果として戻ります。
out に用意した変数が事前に宣言されている変数の場合(例えば rb 変数)には、宣言されていた変数に代入されます。
この辺りは変数のスコープを考えて実装を行う必要があります。

 TryGetComponent メソッドの処理結果が false の場合には Rigidbody コンポーネントの取得ができなかったため、rigid 変数は null のままで、false が処理結果として戻ります''。


 なお TryGetComponent メソッドには複数の書式があります。こちらは下記のリファレンスを参照してください。

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


6.<Input.GetAxis メソッド>


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


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


7.<FixedUpdate メソッド>


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

 FixedUpdate メソッドは初期設定では 0.02秒(1秒間に50回)ごとの固定フレームレートで、物理演算の処理の更新を行う直前に自動的に呼びだされるメソッドです。

 Update メソッドはゲームオブジェクト等の動作のレンダリング前毎フレーム呼び出されますので、
処理の実行タイミングフレームの呼び出しが固定かどうかが Update メソッドと FixedUpdate メソッドの違いです。

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


参考サイト
SamuraiBlog 様
【Unity入門】Updateメソッドとは?FixedUpdateとの違いも徹底解説!
かめくめ 様
UnityのUpdateとFixedUpdate、LateUpdateメソッドについて


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


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



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

  // 移動方向にスピードを掛けて移動
 rb.velocity = new Vector3(moveX, rb.velocity.y, moveZ) * moveSpeed;

 X 軸と Z 軸については、各方向のキー入力の値と moveSpeed 変数の計算結果が入り、その軸の方向へ移動を行います。
Y 軸は velocity 変数の y の値が指定されていますので、重力に影響がある場合にはマイナス方向への速度が入り、
その結果、地面に向かって落下を行っています。

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


参考サイト
Unity公式スクリプトリファレンス
Rigidbody-velocity
SamuraiBlog 様
【Unity入門】Rigidbodyで自在に移動!velocityの活用方法!


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


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

    /// <summary>
    /// 移動
    /// </summary>
    private void Move() {


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

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


10.プレイヤー用のゲームオブジェクトに PlayerMove スクリプトをアタッチする


 ヒエラルキーにあるプレイヤー用のゲームオブジェクトに、先ほど作成した PlayerMove スクリプトをドラッグアンドドロップしてアタッチします。

 ヒエラルキーのプレイヤー用のゲームオブジェクトを選択し、インスペクターを表示して、PlayerMove スクリプトがアタッチされていることを確認します。

 MoveSpeed 変数の値はインスペクターより調整できます。この値がプレイヤー用のゲームオブジェクトの移動速度の値になりますので、適宜調整をお願いします。


<インスペクター画像>



 以上で設定は完了です。


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


 キー入力を行った際に、プレイヤーが実際に移動するか、動作確認(デバッグ)を行います。

 ゲームを実行し、矢印キーの上下左右、あるいは W、S、A、D キーを押し続けてください。
指定した方向に移動すれば、制御は成功です。


 ただし、現時点ではカメラはプレイヤーを追従しませんので、プレイヤーのみが移動する制御になります。
また、プレイヤーの向き(角度)も変化しません

 これらはいずれも、それらの動作に対しての制御が行われていないためです。



 正常に動作した場合、それで終わり、ではなくて、プログラムを読み直し、
どのような処理によって、今回の移動の制御が行われているかを、しっかりと読み解けるようにしてください。

 では続けて、移動に合わせてプレイヤーの向き(角度)を変更する部分について修正を行います。


PlayerMove スクリプトを修正し、プレイヤーの移動方法とプレイヤーのゲームオブジェクトの向き(角度)を一致させる

1.設計


 プレイヤーの用ゲームオブジェクトは移動するようになりましたが、移動するだけであって、ゲームオブジェクトの向きは変更されません。
つまり、ゲームオブジェクトの向き(角度)を一致させるようなプログラムを書かないと、自動的に向きを合わせてくれることはありません。

 このように、いつも遊んでいるゲームで当たり前に動いているように見えるものも、
すべて、内部のプログラムによって制御をしている、ということを認識するようにしていってください。


2.PlayerMove スクリプトを修正する


 ここではプレイヤーのゲームオブジェクトを制御するために作成した PlayerMove スクリプトに処理を追加し、
プレイヤーが移動している場合には、その移動している方向に合わせてゲームオブジェクト(プレイヤー)の向きを変えるためのプログラムを追加します。

 プレイヤーの移動の処理は、内部的にみればゲームオブジェクトの座標の位置の更新によって制御されていますが、
プレイヤーの向きを変える処理は、ゲームオブジェクトの角度の更新によって制御されることになります

PlayerMove.cs

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



2.<Rigidbody.velocity.normalized 変数>


 この情報は、velocity のデータ型である Vector3 に基づいている情報です。
velocity 変数は Vector3 型であるため、Vector3 型に関連する情報を取得することが出来ます。

 そのため、この Rigidbody.velocity.normalized 変数とは、新しい型の情報なのではなくて
Rigidbody 内に用意されている Vector3 型の velocity 変数があり、その velocity 変数とは Vector3 型であるため、
Vector3 型から取得できる normalized 変数の情報を取得している(Vector3.normalized 変数である)、という処理の流れになります。

 変数名に惑わされないように、データ型の内容を見極めていくようにすることで処理が読み解けるようになります。

 なお Vector3.normalized 変数についてはすでに学習済(Unity の教科書など)であるため、自分で再度調べて復習しておくとよいでしょう。


<参考サイト>
Unity公式スクリプト・リファレンス
Vector3.normalized
TechProjin様
UnityのVector3でよく使うものまとめ


3.<Vector3.zero 変数>


 normalized 変数と同じように、Vector3 型に用意されている値です。
この zero 変数は新しく (0, 0, 0) の値をインスタンスします。

 Vector3 型には他にも便利な変数が用意されていますので、覚えておくと効率のよいプログラムを記述することが出来るようになります。

 まずは公式サイトのマニュアルやスクリプトリファレンスに目を通る癖をつけましょう。


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


4.<Quaternion.LookRotation メソッド>


 Quaternion 構造体に用意されている、ゲームオブジェクトを回転させる static メソッドです。
LookRotation メソッドを利用することで、引数に指定した Vector3 型の情報を Quaternion 型に変換します。(戻り値の型が Quaternion 型になっています)


  transform.rotation = Quaternion.LookRotation(rb.velocity.normalized);

 transform.rotation 変数は Vector3 型ではなく、Quaternion 型です。
そのため、Vector3 型の値をそのまま transform.rotation 変数に代入することが出来ません。

 上記のように、Quaternion.LookRotation メソッドを活用することで、Vector3 型の情報を Quaternion 型に変換し、代入処理を成立させています。

 なお、Vector3 型の情報をそのまま回転情報として代入するには、Quaternion.LookRotation メソッドではなく、Transform.eulerAngles 変数を利用します。


参考サイト
Unity 公式スクリプトリファレンス
Quaternion.LookRotation
hildsoftのコード置き場 様
Unityで対象となるオブジェクトを向くように回転させたい(Quaternion.LookRotation)
Unity 公式スクリプトリファレンス
Transform-eulerAngles


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


 追加した処理の内容を見直し、処理の内容を理解した上でゲームを実行して、動作の確認を行います。

 プレイヤーの移動に合わせて、向きが変わり、常に移動する方向を向くようになれば制御成功です。
(カメラの追従制御はまだです)


7.<学習のための工夫>


 なお、角度の制御する処理には if 文による分岐がありました。
この分岐の理由を確かめるためにも、一度、分岐の部分をコメントアウトしてみましょう。
角度の制御について、予期していない処理が発生することがわかると思います。


<スクリプトによる制御の確認>
        //if (rb.velocity.normalized != Vector3.zero) {

            // if 文による分岐をなくし、この処理を、常に動く処理に変更してみる
            transform.rotation = Quaternion.LookRotation(rb.velocity.normalized);
        //}

 気になった部分はこのようにして、処理のコメントアウトなどをすることで、どういった処理が動いているのかを理解する上で役立ちます。
学習には工夫が必要です。プログラムへの理解を深めていくためにはどういったことを考えればいいのか、自分なりに考えていくことが重要です。


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

 => 次は 手順6 ーカメラの追従機能の実装ー です。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3Dレールガンシューティング(応用編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます