Contents
概要
以前に以下の記事でUnityの新規プロジェクトの作成からUnity Assetとして提供されているキャラクターオブジェクトの「Robot Kyle」をSceneへ配置するところまでの流れを紹介しました。
今回はその続きとしてキーボード入力でRobot Kyleを操作する方法について紹介していきます。
環境
Windows10
Unity 2020.1.f1
目的
キーボード入力からRobotKyleの操作の実現を目指します。具体的には以下を行えるようにしたいと思います。
- キーボードの↑↓ボタンで前後に進む
- キーボードの←→ボタンで方向転換する
- スペースキーでジャンプする
- Shift + ↑↓ボタンでダッシュで前後に進む
今回はキャラクターにアニメーションは付けずに、初期姿勢のまま位置と姿勢のみ動かす、というところまでを目指します。
Step1 : コンポーネント類の追加
Robot Kyleを動かすにあたり物理計算を行うためのRigidbodyと、衝突を管理するためのColliderのコンポーネントを設定していきます。
Rigidbodyの追加
まずはRigidbodyを追加します。
HierachyからRobot Kyleを選択し、InspectorタブからAdd Componentを選択します。

検索ボックスが現れますので”rigid”などと打ってRigidbodyが出てきたら選択します。

Rigidbodyのパラメータはデフォルトのままで問題ありません。

Colliderの追加
同様にColliderも追加していきます。Add Componentから”collider”と入力し、Capsule Colliderを選択します。

Capsule Colliderの設定値はうまいくRobot Kyleの体が収まるくらいに調整するのが良いです。ここでは以下のように設定しています。
Y | 0.9 |
Radius | 0.3 |
Height | 1.8 |

Step2 : Main Cameraの設定
次にMain Cameraの設定を行います.
HierarchyのMain Cameraをドラッグ&ドロップでRobot Kyleの配下に配置します。


次に、Main CameraのInspectorでTransformを調整します。
ここは好みになりますが、私の場合はRobot Kyleのなるべく全身を映るようにしたかったため、以下のように設定してあります。
X : 0
Y : 1.5
Z : -2.5

Step3: 操作スクリプトの作成
ProjectタブのAsset上で右クリックし、Create > C# Scriptからscriptファイルを新規作成し、PlayerConという名前を付けます。

作成したスクリプトに操作の部分を書いていくのですが、大まかに以下の方針で進めることにしました。
- 移動はTransform.positionを使用して制御する。
- ジャンプ中に空中で移動はできないようにする
- 斜め前にもジャンプできるようにする
- 二段ジャンプは禁止する
スクリプト全体
【PlayerCon.cs】
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerCon : MonoBehaviour { // Start is called before the first frame update //キャラクターの操作状態を管理するフラグ [SerializeField] public bool onGround = true; [SerializeField] public bool inJumping = false; //rigidbodyオブジェクト格納用変数 Rigidbody rb; //移動速度の定義 float speed = 6f; //ダッシュ速度の定義 float sprintspeed = 9f; //方向転換速度の定義 float angleSpeed = 200; //移動の係数格納用変数 float v; float h; void Start() { //Shift+上下キーでダッシュ、上下キーで通常移動,それ以外は停止 if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.LeftShift)) v = Time.deltaTime * sprintspeed; else if (Input.GetKey(KeyCode.DownArrow) && Input.GetKey(KeyCode.LeftShift)) v = -Time.deltaTime * sprintspeed; else if (Input.GetKey(KeyCode.UpArrow)) v = Time.deltaTime * speed; else if (Input.GetKey(KeyCode.DownArrow)) v = -Time.deltaTime * speed; else v = 0; //移動の実行 if (!inJumping)//空中での移動を禁止 { transform.position += transform.forward * v; } //スペースボタンでジャンプする if (onGround) { if (Input.GetKey(KeyCode.Space)) { //ジャンプさせるため上方向に力を発生 rb.AddForce(transform.up * 8, ForceMode.Impulse); //ジャンプ中は地面との接触判定をfalseにする onGround = false; inJumping = true; //前後キーを押しながらジャンプしたときは前後方向の力も発生 if (Input.GetKey(KeyCode.UpArrow)) { rb.AddForce(transform.forward * 6f,ForceMode.Impulse); } else if (Input.GetKey(KeyCode.DownArrow)) { rb.AddForce(transform.forward * -3f, ForceMode.Impulse); } } } //左右キーで方向転換 if (Input.GetKey(KeyCode.RightArrow)) h = Time.deltaTime * angleSpeed; else if (Input.GetKey(KeyCode.LeftArrow)) h = -Time.deltaTime * angleSpeed; else h = 0; //方向転換動作の実行 transform.Rotate(Vector3.up * h); } //地面に接触したときにはonGroundをtrue、injumpingをfalseにする void OnCollisionEnter(Collision col) { if(col.gameObject.tag=="Ground") { onGround = true; inJumping = false; } } }
スクリプトの中身について順を追って紹介します。
void Start部
今回、Playerの回転を止める際とジャンプするための力を発生させるためにRigidbodyを使用します。そのため初めにPlayerのRigidbody関連のオブジェクトを取得しておきます。
rb = this.GetComponent<Rigidbody>(); rb.constraints = RigidbodyConstraints.FreezeRotation;
void Update部
前後方向の移動速度定義
押下しているキーに応じて前後方向の速度を変化させています。
Shiftと方向ボタンを押したときはダッシュ速度(sprintspeed)、方向ボタンの場合は通常移動速度(speed)を使用しています。
if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.LeftShift)) v = Time.deltaTime * sprintspeed; else if(Input.GetKey(KeyCode.DownArrow) && Input.GetKey(KeyCode.LeftShift)) v = -Time.deltaTime * sprintspeed; else if(Input.GetKey(KeyCode.UpArrow)) v = Time.deltaTime * speed; else if(Input.GetKey(KeyCode.DownArrow)) v = -Time.deltaTime * speed; else v = 0; //移動の実行 if (!inJumping)//空中での移動を禁止 { transform.position += transform.forward * v; }
方向転換
- 方向転換のベクトル定義
- transform.Rotateで回転
//左右キーで方向転換 if (Input.GetKey(KeyCode.RightArrow)) h = Time.deltaTime * angleSpeed; else if (Input.GetKey(KeyCode.LeftArrow)) h = -Time.deltaTime * angleSpeed; else h = 0;
ジャンプ
ジャンプする条件としてスペースキーの押下とキャラクターが地面に接触していることとしています。これにより空中での二段ジャンプを禁止しています。
Addforceを使用して上方向の力を発生させることでジャンプをさせています。また、前後方向キーを押しながらスペースキーを押すことで、前方向の力も同時に発生させ、斜め前にジャンプするようにしています。後ろ向きの場合は少し力を弱めています。
//スペースボタンでジャンプする if (Input.GetKey(KeyCode.Space) && onGround) { //ジャンプ時の初期速度を0に設定 rb.velocity = new Vector3(0, 0, 0); //ジャンプさせるため上方向に力を発生 rb.AddForce(transform.up * 300); //前方向キーを押しながらのジャンプの時には後方向に力を発生させる if (Input.GetKey(KeyCode.UpArrow)) rb.AddForce(transform.forward * 180); //後ろ方向キーを押しながらのジャンプの時には後方向に力を発生させる else if (Input.GetKey(KeyCode.DownArrow)) rb.AddForce(transform.forward * -100); //ジャンプ中は地面との接触判定をfalseにする onGround = false; }
OnCollisionEnter部
予め地面にGroundタグをつけておき、キャラクターが地面と接触した場合にはonGroundをtrueにします。また、inJumpingをfalseにします。
//地面に接触したときにはonGroundをtrue、injumpingをfalseにする void OnCollisionEnter(Collision col) { if(col.gameObject.tag=="Ground") { onGround = true; inJumping = false; } }注意事項:TerrianにGroundタグが付いていること、Robot KyleのCapsule Colliderのis Trigerにチェックが入っていないこと
まとめ
今回はキーボードでRobot Kyleを動かすところまでを実践しました。ただ、この状態だとまだアニメーションがついていないので、味気ないです。次回はさらにこのスクリプトを改良し、アニメーションをつけていきたいと思います。
[…] […]