Unityでキャラクターを移動させる方法【3D編】

移動方法は大きく分けて「transformを使った移動」「Rigidbodyを使った移動」「CharactorControllerを使った移動」「Vectorを使った移動」の4つがあります(「Vectorを使った移動」」は指定位置まで自動的に動く(入力による移動ではない)ためか除かれていることが多いですが、ここでは含めます)。この分類に入らない移動方法もありますが、それはいったん「その他の移動方法」としてまとめます。
なお、「キャラクターの移動」といった場合、「位置を変える」「向きを変える」「アニメーションを変える」の3つの処理を合わせて説明していることが多いですが、ここでは「位置を変える」方法のみを取り上げています。「向きを変える」「アニメーションを変える」方法については別途まとめます。
環境
- Unity 5.6.0f3
- このページで使用している環境の設定方法はこちらから
移動方法の分類
- transformを使った移動
- オブジェクトのトランスフォーム情報(座標)を直接書き換える方法
- transform.positionを書き換えて移動する
- transform.Translateを使って移動する
- Rigidbodyを使った移動
- オブジェクトにRigidbodyをアタッチして、物理的に力を加える方法
- Rigidbody.AddForceを使って移動する
- Rigidbody.velocityを書き換えて移動する
- Rigidbody.MovePositionを使って移動する
- CharactorControllerを使った移動
- CharactorControllerをアタッチして、移動機能を呼び出して動かす方法
- CharactorController.SimpleMoveを使って移動する
- CharactorController.Moveを使って移動する
- Vectorを使った移動
- Vectorで移動先を指定して動かす方法
- Vector3.MoveTowardsを使って移動する
- Vector3.Lerp(Vector3.Slerp)を使って移動する
- その他の移動方法
- 上記分類に含まれない移動方法
- NavMeshを使って移動する
transformを使った移動
- 重力を加えるため、Rigidbodyをアタッチ
- 床との接触判定のため、CapsuleColliderをアタッチ
- 位置を直接書き換えているため、衝突判定をすり抜けやすい(ある意味、短いワープの連続)
transform.positionを書き換えて移動する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public float speed = 3.0f; // Update is called once per frame void Update () { if (Input.GetKey ("up")) { transform.position += transform.forward * speed * Time.deltaTime; } if (Input.GetKey ("down")) { transform.position -= transform.forward * speed * Time.deltaTime; } if (Input.GetKey("right")) { transform.position += transform.right * speed * Time.deltaTime; } if (Input.GetKey ("left")) { transform.position -= transform.right * speed * Time.deltaTime; } } |
transform.Translateを使って移動する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void Update () { if (Input.GetKeyDown (KeyCode.UpArrow)) { transform.Translate (0, 0, 3); } if (Input.GetKeyDown (KeyCode.DownArrow)) { transform.Translate (0, 0, -3); } if (Input.GetKeyDown (KeyCode.LeftArrow)) { transform.Translate (-3, 0, 0); } if (Input.GetKeyDown (KeyCode.RightArrow)) { transform.Translate (3, 0, 0); } } |
- この移動方法の参考リンク
- 公式スクリプトリファレンス(Unity 5.4)
- 公式スクリプトリファレンス(日本語版最新)
- キャラクターの移動<3D編> 2016.4.7
→滑らかに移動させる方法が説明されています。
Rigidbodyを使った移動
- Rigidbodyコンポーネントをアタッチしておく必要がある
- 衝突判定には以下の2つの条件が必要。少なくとも片方のオブジェクトにRigidbodyがアタッチされていること、両方のオブジェクトにcolliderがアタッチされていること
Rigidbody.AddForceを使って移動する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public float speed = 10.0f; public Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void FixedUpdate() { float x = Input.GetAxis("Horizontal") * speed; float z = Input.GetAxis("Vertical") * speed; rb.AddForce(x , 0 , z ); } |
Rigidbody.velocityを書き換えて移動する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public float speed = 3f; float moveX = 0f; float moveZ = 0f; Rigidbody rb; void Start(){ rb = GetComponent<Rigidbody> (); } void Update () { moveX = Input.GetAxis ("Horizontal") * speed; moveZ = Input.GetAxis ("Vertical") * speed; Vector3 direction = new Vector3(moveX , 0, moveZ); } void FixedUpdate(){ rb.velocity = new Vector3(moveX, 0, moveZ); } |
Rigidbody.MovePositionを使って移動する
- 公式スクリプトリファレンスを見ると「Rigidbody interpolation(補間)を有効にした場合、Rigidbody.MovePosition を呼び出すとレンダリングされる中間フレームで2つの位置の間のスムーズな遷移となります。」と書いてあるが、ワープしているように見える。この記述の詳細は不明。
1 2 3 4 5 6 7 8 9 10 11 12 |
public Vector3 teleportPoint = new Vector3(0, 5, 10); public Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void FixedUpdate() { //以下の記述では一定速度で前に進む //rb.MovePosition(transform.position + transform.forward * Time.deltaTime); //以下の記述ではteleportPointにワープ rb.MovePosition(teleportPoint); } |
CharactorControllerを使った移動
- CharactorControllerコンポーネントをアタッチしておく必要がある
- CharactorControllerはカプセルコライダーと移動機能をセットにしたコンポーネント
- rigidbodyに影響されない形でゲームオブジェクトを操作することができる
- 基本的に重力が効かないので、スクリプトで重力相当の力を加える必要がある(rigidbodyをアタッチしても効かない)
- 接触の検知はOnControllerColliderHitを使う
CharactorController.SimpleMoveを使って移動する
- CharactorControllerを使うと物理演算は基本効かないが、SimpleMoveを使った移動では重力が自動的に加えられる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public float speed = 3.0f; float moveX = 0f; float moveZ = 0f; CharacterController controller; void Start(){ controller = GetComponent<CharacterController>(); } void Update() { moveX = Input.GetAxis ("Horizontal") * speed; moveZ = Input.GetAxis ("Vertical") * speed; Vector3 direction = new Vector3(moveX , 0, moveZ); controller.SimpleMove(direction); } |
CharactorController.Moveを使って移動する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public float speed = 3.0f; public float gravity = 9.81f; private Vector3 moveDirection = Vector3.zero; CharacterController controller; void Start(){ controller = GetComponent<CharacterController>(); } void Update() { if (controller.isGrounded) { moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); moveDirection = transform.TransformDirection(moveDirection); moveDirection *= speed; } moveDirection.y -= gravity * Time.deltaTime; controller.Move(moveDirection * Time.deltaTime); } |
- この移動方法の参考リンク
- 公式スクリプトリファレンス(Unity 5.4)
- 公式スクリプトリファレンス(日本語版最新)
- CharacterControllerをつかってプレーヤーを動かす 2016.9.4
- Unityでキャラクターの移動をプログラミングしてみる 2017.3.9
- プレーヤーキャラクターを動かす 2014.6.13
- この移動方法でゲームを作っている本
Vectorを使った移動方法
Vector3.MoveTowardsを使って移動する
- 指定した位置まで一定速度で移動させてくれる
- 画像では最初、少し引っ掛かりがあるように見えますが、もっと滑らかに動きます
- 重力が効いているとぴょんぴょん跳んでいるようになるので、画像では重力は切っています
1 2 3 4 5 6 7 |
Vector3 target = new Vector3(0, 5, 10); public float speed = 3.0f; void Update() { float step = speed * Time.deltaTime; transform.position = Vector3.MoveTowards(transform.position, target, step); } |
Vector3.Lerp(Vector3.Slerp)を使って移動する
- 指定した位置まで滑らかに移動させてくれる
- LerpとSlerpはほぼ同じだが、少し動き方が変わる(特に動き始めと動き終わり)
- 重力が効いているとぴょんぴょん跳んでいるようになるので、画像では重力は切っています
1 2 3 4 5 6 |
Vector3 target = new Vector3(0, 5, 10); void Update() { transform.position = Vector3.Lerp(transform.position, target, Time.deltaTime); //transform.position = Vector3.Slerp(transform.position, target, Time.deltaTime); } |
その他の移動方法
NavMeshを使って移動する
NavMeshについては別途まとめる予定です
1 thought on “Unityでキャラクターを移動させる方法【3D編】”