07「玉転がし」Roll a Ball – プレイヤーの追加

プレイヤーの追加

自分が操作する、ボールを作成します。

Sceneにプレイヤーを作成

シーン上にプレイヤーを作成します。

  1. Hierarchyビューの「+」ボタンをクリックします。
  2. 3D Object → Sphereを選択します。
  3. Shphereの名前を「Player」に変更します。
  4. Playerの座標を以下の値に変更します。
    Position(x:0, y:0.5, z:0)

Rigidbodyを追加する

Playerに物理挙動を追加します。

  1. HierarchyビューのPlayerを選択します。
  2. InspectorビューのAdd Componentボタンをクリックします。
  3. 検索バーに「rigidbody」と入力し、表示されたRigidbodyを選択します。
    ※Rigidbody2Dは使用しません。

PlayerInputを追加する

プレイヤーの入力を受け付けるためのコンポーネントを追加します。

※この時点では、まだPlayerを動かすことはできません。

  1. HierarchyビューのPlayerを選択します。
  2. InspectorビューのAdd Componentボタンをクリックします。
  3. 検索バーに「player input」と入力し、表示されたPlayerInputを選択します。

スクリプトファイルの作成

プレイヤーを操作するためのスクリプトファイルを作成します。

  1. HierarchyビューのPlayerを選択します。
  2. InspectorビューのAdd Componentボタンをクリックします。
  3. 検索バーに「new script」と入力し、表示されたNew scriptを選択します。
  4. Nameに「PlayerController」と入力し、Create and Addボタンをクリックします。
  5. Projectビューの「+」をクリックします。
  6. Folderを選択します。
  7. Folderの名前を「Scripts」に変更します。
  8. ProjectビューのPlayerContrllerを選択し、Scriptsフォルダーにドラックアンドドロップします。

スクリプトエディターの起動

スクリプトファイルに処理を追加するにあたり、スクリプトエディターを起動します。

  1. ProjectビューのScriptsフォルダー内にあるPlayerContrllerをダブルクリック(左クリック2回)します。
    UnityEditorで設定されているスクリプトエディター(Visual Studio/Visual Studio Codeなど)が起動します。
    • Visual Stduioを使用している場合
    • Visual Stdio Codeを使用している場合

この資料のスクリプトの説明

スクリプトの作成では頻繁に命令の追加/削除/編集が起こります。そのためこの資料での表記は以下のように扱います。

ファイル名

+ 命令の追加
- 命令の削除

先頭に+がついている行は追加した命令です。

先頭に-がついている行は削除した命令です。

また、資料の中ではコメントアウト///**//// <summary> ///</summary>にも先頭に+/-を付けますが、実際に書いてもいいですし、書かなくてもいいです。
なるべく書いた方が見やすくなります。また、自分の勉強/メモ用のコメントを残しておくと覚えやすくなります。

入力データを受け取りPlayerオブジェクトを動かす

キーボード/ゲームパッドからの入力を受け付ける処理をPlayerController.csに追加します。

Unityで作成したスクリプトにはデフォルトでStartUpdateの2つの関数が含まれています。

Start関数はゲームの開始時に呼び出され、Update関数はゲームのフレームごとに1回呼び出されます(60fpsの場合、1秒間に60回呼び出される)。

  1. このスクリプトではUpdate関数は使用しないため削除します。また、デフォルトでされているコメントアウトも削除します。

PlayerController.cs

using UnityEngine;

public class PlayerContrller : MonoBehaviour
{
-    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {

    }
-
-    // Update is called once per frame
-    void Update()
-    {
-        
-    }
}
  1. 入力を受け付けるのに必要なInputSystemの名前空間を追加します。

InputSystemのドキュメント(InputSystem

PlayerController.cs

using UnityEngine;
+ // PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
+ // キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) → 
+ // PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
+ using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{
    void Start()
    {

    }
}
  1. キーボードのW/A/S/D・ゲームパッドのLスティックからの入力を受け取るOnMove関数の追加をします。

PlayerController.cs

using UnityEngine;
// PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
// キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) → 
// PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{
    void Start()
    {

    }
+
+    /// <summary>
+    /// プレイヤーのキーボード(WASD)/ゲームパッド(Lスティック)の入力があった際に呼び出される関数です。
+    /// </summary>
+    /// <param name="movementValue">入力デバイスのX方向とY方向の値を持っています。</param>
+    void OnMove(InputValue movementValue)
+    {
+        
+    }
}
  1. movementValue(InputValue型)から2次元座標(X/Y)のデータに変換し変数に保存します。

PlayerController.cs

using UnityEngine;
// PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
// キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) → 
// PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{
    void Start()
    {

    }

    /// <summary>
    /// プレイヤーのキーボード(WASD)/ゲームパッド(Lスティック)の入力があった際に呼び出される関数です。
    /// </summary>
    /// <param name="movementValue">入力デバイスのX方向とY方向の値を持っています。</param>
    void OnMove(InputValue movementValue)
    {
+        // Vecotr2(2次元座標:X座標/Y座標)型の変数movementVecotrにmovementValueをVector2(2次元座標)に変換し保存します。
+        Vector2 movementVector = movementValue.Get<Vector2>();
    }
}
  1. movementVector(Vector2型)のX座標/Y座標の値を変数_movmentX/_movmentYに保存します。

PlayerController.cs

using UnityEngine;
// PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
// キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) → 
// PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{

+    // private(プライベート)で定義する変数の名前は最初に_(アンダーバー)を付けます。
+    // private変数は他のスクリプトファイルから値を取得・変更させることができない変数です。
+
+    /// <summary>
+    /// X方向の移動量を保存する変数
+    /// </summary>
+    private float _movementX;
+
+    /// <summary>
+    /// Y方向の移動量を保存する変数
+    /// </summary>
+    private float _movementY;
+
    void Start()
    {

    }

    /// <summary>
    /// プレイヤーのキーボード(WASD)/ゲームパッド(Lスティック)の入力があった際に呼び出される関数です。
    /// </summary>
    /// <param name="movementValue">入力デバイスのX方向とY方向の値を持っています。</param>
    void OnMove(InputValue movementValue)
    {
        // Vecotr2(2次元座標:X座標/Y座標)型の変数movementVecotrにmovementValueをVector2(2次元座標)に変換し保存します。
        Vector2 movementVector = movementValue.Get<Vector2>();
+
+        // movementVectorのX座標・Y座標をそれぞれに変数に保存します。
+        _movementX = movementVector.x;
+        _movementY = movementVector.y;
    }
}
  1. 物理演算をするFixedUpdate関数を追加します。

FixedUpdate関数は物理演算を実行する直前に呼び出されます。
一方、最初に削除したUpdate関数はフレームをレンダリングする前に呼び出されます。

物理演算をする命令をする場合FixedUpdate関数に書くようにします。

PlayerController/cs

using UnityEngine;
// PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
// キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) → 
// PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{

    // private(プライベート)で定義する変数の名前は最初に_(アンダーバー)を付けます。
    // private変数は他のスクリプトファイルから値を取得・変更させることができない変数です。

    /// <summary>
    /// X方向の移動量を保存する変数
    /// </summary>
    private float _movementX;

    /// <summary>
    /// Y方向の移動量を保存する変数
    /// </summary>
    private float _movementY;

    void Start()
    {

    }

    /// <summary>
    /// プレイヤーのキーボード(WASD)/ゲームパッド(Lスティック)の入力があった際に呼び出される関数です。
    /// </summary>
    /// <param name="movementValue">入力デバイスのX方向とY方向の値を持っています。</param>
    void OnMove(InputValue movementValue)
    {
        // Vecotr2(2次元座標:X座標/Y座標)型の変数movementVecotrにmovementValueをVector2(2次元座標)に変換し保存します。
        Vector2 movementVector = movementValue.Get<Vector2>();

        // movementVectorのX座標・Y座標をそれぞれに変数に保存します。
        _movementX = movementVector.x;
        _movementY = movementVector.y;
    }
+
+    void FixedUpdate()
+    {
+
+    }
}
  1. Rigidbodyを保存する変数の追加とPlayerにアタッチされたRibidbodyを取得し保存します。

GetComponent関数を使用するとオブジェクトにアタッチされているコンポーネントを取得できます。

PlayerController.cs

using UnityEngine;
// PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
// キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) → 
// PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{
    // private(プライベート)で定義する変数の名前は最初に_(アンダーバー)を付けます。
    // private変数は他のスクリプトファイルから値を取得・変更させることができない変数です。
+
+    /// <summary>
+    /// PlayerにアタッチされたRigidbodyを保存する変数
+    /// </summary>
+    private Rigidbody _rb;

    /// <summary>
    /// X方向の移動量を保存する変数
    /// </summary>
    private float _movementX;

    /// <summary>
    /// Y方向の移動量を保存する変数
    /// </summary>
    private float _movementY;

    void Start()
    {
+        // PlayerにアタッチされたRigidbodyを取得し変数_rbに保存します。
+        _rb = GetComponent<Rigidbody>();
    }

    /// <summary>
    /// プレイヤーのキーボード(WASD)/ゲームパッド(Lスティック)の入力があった際に呼び出される関数です。
    /// </summary>
    /// <param name="movementValue">入力デバイスのX方向とY方向の値を持っています。</param>
    void OnMove(InputValue movementValue)
    {
        // Vecotr2(2次元座標:X座標/Y座標)型の変数movementVecotrにmovementValueをVector2(2次元座標)に変換し保存します。
        Vector2 movementVector = movementValue.Get<Vector2>();

        // movementVectorのX座標・Y座標をそれぞれに変数に保存します。
        _movementX = movementVector.x;
        _movementY = movementVector.y;
    }

    void FixedUpdate()
    {

    }
}
  1. Playerにある方向に対して力を加える(もの押し出すイメージ)物理演算をする命令を追加します

変数_movmentX/_movmentYの値からVector3(3次元座標:X/Y/Z)の値を作成し変数movementに保存します。
※Y座標を上下です。Playerはジャンプしないので0.0fにしています。
RigidBodyが持っているAddForce関数を使うことでPlayerに力を加えることができます。

PlayerController.cs

using UnityEngine;
// PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
// キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) → 
// PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{
    // private(プライベート)で定義する変数の名前は最初に_(アンダーバー)を付けます。
    // private変数は他のスクリプトファイルから値を取得・変更させることができない変数です。

    /// <summary>
    /// PlayerにアタッチされたRigidbodyを保存する変数
    /// </summary>
    private Rigidbody _rb;

    /// <summary>
    /// X方向の移動量を保存する変数
    /// </summary>
    private float _movementX;

    /// <summary>
    /// Y方向の移動量を保存する変数
    /// </summary>
    private float _movementY;

    void Start()
    {
        // PlayerにアタッチされたRigidbodyを取得し変数_rbに保存します。
        _rb = GetComponent<Rigidbody>();
    }

    /// <summary>
    /// プレイヤーのキーボード(WASD)/ゲームパッド(Lスティック)の入力があった際に呼び出される関数です。
    /// </summary>
    /// <param name="movementValue">入力デバイスのX方向とY方向の値を持っています。</param>
    void OnMove(InputValue movementValue)
    {
        // Vecotr2(2次元座標:X座標/Y座標)型の変数movementVecotrにmovementValueをVector2(2次元座標)に変換し保存します。
        Vector2 movementVector = movementValue.Get<Vector2>();

        // movementVectorのX座標・Y座標をそれぞれに変数に保存します。
        _movementX = movementVector.x;
        _movementY = movementVector.y;
    }

    void FixedUpdate()
    {
+       // _movmentXをX軸の値に_movmentYをZ軸の値にした3次元座標に変換し変数momventに保存します。
+        Vector3 movement = new Vector3(x: _movementX, y: 0.0f, z: _movementY);
+
+        // RigidbodyのAddFrouce関数に3次元座標を渡し、指定した方向に力を加えます。
+        _rb.AddForce(movement);
    }
}

ここまで出来たらファイルを保存します。(Windows:Ctrl + C/Mac:Command + C

ゲームをテストする

UnityEditorに戻り実行ボタンを押し操作します。

Playerはゆっくりと動くはずです。

実行を終了したい場合は停止ボタンを押します。

Playerの移動速度を修正

現状、Playerはゆっくりと動くので、移動速度を変化させます。

  1. パブリック変数speedを追加します

変数をpublic(パブリック)にすることでUnityEditor上で値を変更することができます。

PlayerController.cs

using UnityEngine;
// PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
// キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) → 
// PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{
+    /// <summary>
+    /// Playerの移動速度を保存する変数
+    /// </summary>
+    public float speed = 5f;
+
    // private(プライベート)で定義する変数の名前は最初に_(アンダーバー)を付けます。
    // private変数は他のスクリプトファイルから値を取得・変更させることができない変数です。

    /// <summary>
    /// PlayerにアタッチされたRigidbodyを保存する変数
    /// </summary>
    private Rigidbody _rb;

    /// <summary>
    /// X方向の移動量を保存する変数
    /// </summary>
    private float _movementX;

    /// <summary>
    /// Y方向の移動量を保存する変数
    /// </summary>
    private float _movementY;

    void Start()
    {
        // PlayerにアタッチされたRigidbodyを取得し変数_rbに保存します。
        _rb = GetComponent<Rigidbody>();
    }

    /// <summary>
    /// プレイヤーのキーボード(WASD)/ゲームパッド(Lスティック)の入力があった際に呼び出される関数です。
    /// </summary>
    /// <param name="movementValue">入力デバイスのX方向とY方向の値を持っています。</param>
    void OnMove(InputValue movementValue)
    {
        // Vecotr2(2次元座標:X座標/Y座標)型の変数movementVecotrにmovementValueをVector2(2次元座標)に変換し保存します。
        Vector2 movementVector = movementValue.Get<Vector2>();

        // movementVectorのX座標・Y座標をそれぞれに変数に保存します。
        _movementX = movementVector.x;
        _movementY = movementVector.y;
    }

    void FixedUpdate()
    {
        // _movmentXをX軸の値に_movmentYをZ軸の値にした3次元座標に変換し変数momventに保存します。
        Vector3 movement = new Vector3(x: _movementX, y: 0.0f, z: _movementY);

        // RigidbodyのAddFrouce関数に3次元座標を渡し、指定した方向に力を加えます。
        _rb.AddForce(movement);
    }
}
  1. movmentとspeedを掛け合わせた値をAddForceに渡します

PlayerController.cs

using UnityEngine;
// PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
// キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) → 
// PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{
    /// <summary>
    /// Playerの移動速度を保存する変数
    /// </summary>
    public float speed = 5f;

    // private(プライベート)で定義する変数の名前は最初に_(アンダーバー)を付けます。
    // private変数は他のスクリプトファイルから値を取得・変更させることができない変数です。

    /// <summary>
    /// PlayerにアタッチされたRigidbodyを保存する変数
    /// </summary>
    private Rigidbody _rb;

    /// <summary>
    /// X方向の移動量を保存する変数
    /// </summary>
    private float _movementX;

    /// <summary>
    /// Y方向の移動量を保存する変数
    /// </summary>
    private float _movementY;

    void Start()
    {
        // PlayerにアタッチされたRigidbodyを取得し変数_rbに保存します。
        _rb = GetComponent<Rigidbody>();
    }

    /// <summary>
    /// プレイヤーのキーボード(WASD)/ゲームパッド(Lスティック)の入力があった際に呼び出される関数です。
    /// </summary>
    /// <param name="movementValue">入力デバイスのX方向とY方向の値を持っています。</param>
    void OnMove(InputValue movementValue)
    {
        // Vecotr2(2次元座標:X座標/Y座標)型の変数movementVecotrにmovementValueをVector2(2次元座標)に変換し保存します。
        Vector2 movementVector = movementValue.Get<Vector2>();

        // movementVectorのX座標・Y座標をそれぞれに変数に保存します。
        _movementX = movementVector.x;
        _movementY = movementVector.y;
    }

    void FixedUpdate()
    {
        // _movmentXをX軸の値に_movmentYをZ軸の値にした3次元座標に変換し変数momventに保存します。
        Vector3 movement = new Vector3(x: _movementX, y: 0.0f, z: _movementY);

        // RigidbodyのAddFrouce関数に3次元座標を渡し、指定した方向に力を加えます。
-        _rb.AddForce(movement);
+        // movment(力)にspeed(移動速度)掛け合わせます。
+        _rb.AddForce(movement * speed);
    }
}

ここまで出来たらファイルを保存します。(Windows:Ctrl + C/Mac:Command + C

ゲームをテスト

UntiyEditorに戻ります。

変数speedをpublic(パブリック)にしたため、UnityEditor上で値を変更することができます。

HierarchyビューのPlayerを選択し、InspectorビューのPlayerControllerのSpeedを好きな値に変更することができます。

実行ボタンを押し、移動速度が変わっているか確認します。

移動速度が変わっていることが確認出来たら停止します。

PlayerControllerの最終スクリプト

PlayerContrller.cs

using UnityEngine;
// PlayerゲームオブジェクトにアタッチしたPlayerInputからの入力を受け付けるために必要な名前空間
// キーボード/ゲームパッド → Actions(ProjectビューにあるInputSystem_Actionsファイル) →
// PlayerゲームオブジェクトにアタッチしたPlyaerInput → このスクリプト
using UnityEngine.InputSystem;

public class PlayerContrller : MonoBehaviour
{
    /// <summary>
    /// Playerの移動速度を保存する変数
    /// </summary>
    public float speed = 5f;

    // private(プライベート)で定義する変数の名前は最初に_(アンダーバー)を付けます。
    // private変数は他のスクリプトファイルから値を取得・変更させることができない変数です。

    /// <summary>
    /// PlayerにアタッチされたRigidbodyを保存する変数
    /// </summary>
    private Rigidbody _rb;

    /// <summary>
    /// X方向の移動量を保存する変数
    /// </summary>
    private float _movementX;

    /// <summary>
    /// Y方向の移動量を保存する変数
    /// </summary>
    private float _movementY;

    void Start()
    {
        // PlayerにアタッチされたRigidbodyを取得し変数_rbに保存します。
        _rb = GetComponent<Rigidbody>();
    }

    /// <summary>
    /// プレイヤーのキーボード(WASD)/ゲームパッド(Lスティック)の入力があった際に呼び出される関数です。
    /// </summary>
    /// <param name="movementValue">入力デバイスのX方向とY方向の値を持っています。</param>
    void OnMove(InputValue movementValue)
    {
        // Vecotr2(2次元座標:X座標/Y座標)型の変数movementVecotrにmovementValueをVector2(2次元座標)に変換し保存します。
        Vector2 movementVector = movementValue.Get<Vector2>();

        // movementVectorのX座標・Y座標をそれぞれに変数に保存します。
        _movementX = movementVector.x;
        _movementY = movementVector.y;
    }

    void FixedUpdate()
    {
        // _movmentXをX軸の値に_movmentYをZ軸の値にした3次元座標に変換し変数momventに保存します。
        Vector3 movement = new Vector3(x: _movementX, y: 0.0f, z: _movementY);

        // RigidbodyのAddFrouce関数に3次元座標を渡し、指定した方向に力を加えます。
        // movment(力)にspeed(移動速度)掛け合わせます。
        _rb.AddForce(movement * speed);
    }
}