主なコンテンツ

〜主なコンテンツ〜

1. Unityで製作したゲームと製作Tips
  1. 三月精チャレンジ(東方Project二次創作)
    1. 作り方
  2. 英語学習2D(オリジナルスマホアプリ)
2. UE4
3. ゲームアプリ見学
4. Bitbucket & SourceTreeでの一連の流れ
  1. 前半
  2. 後半
5. Tips
  1. UnityのTips
  5. SQL文のTips
  6. Final IK
  7. GearVR+Unity

2016年3月8日火曜日

カメラを基準としたプレイヤーの移動【三月精チャレンジ】

■カメラを基準とする理由

次の画像のようにカメラの映像がワールド空間と一致する場合

void Move(){
float h = Input.GetAxisRaw ("Horizontal");
float v = Input.GetAxisRaw ("Vertical");
Vector3 movement = new Vector3(h, 0f, v);
movement = movement.normalized * speed * Time.deltaTime;
playerRigidbody.MovePosition (transform.position + movement);
}

のようにして動かすことができる。


しかし、カメラの映像がワールド空間と一致しない場合はこの手段は使えない。例えば、次の図のようにキャラクターを右側面から映した場合を考える。このとき前述のスクリプトで上入力をした場合、キャラクターはワールド空間の上方向に移動するが、カメラから見ると右方向に移動しているように見える。


よって、Input.GetAxis ("Vertical")によるプレイヤーの移動方向はカメラのforward軸、Input.GetAxis ("Horizontal")によるプレイヤーの移動方向はカメラのright軸にする必要がある。要はプレイヤー移動はワールド空間ではなく、カメラのローカル空間で考える必要がある。また、Rigidbody.MovePosition等のGameObjectを移動させるための関数はワールド空間で計算するため、ローカル空間とワールド空間の変換が必要となる。

なお、カメラに仰角俯角をつけているとその方向を進行方向とみなしてしまうため、XZ平面を移動させたい場合はy成分を除去しておく必要がある。最終的なスクリプトは下記。

■スクリプト全体(プレイヤーにアタッチ)

using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
[SerializeField]
private float speed =3.5f;
private Rigidbody playerRig;
private Vector3 movement;//<! 移動先の座標(Updateで更新する)
// Use this for initialization
void Start () {
playerRig = GetComponent<Rigidbody> ();
}
// Update is called once per frame
void Update () {
//移動先座標の更新
UpdateMovement ();
//移動
Move();
//回転
Turn();
}
void UpdateMovement(){
//ワールド空間でのカメラのforwardを取得、XZ成分を抽出したもので正規化
Vector3 forward = Camera.main.transform.TransformDirection(Vector3.forward);
forward.y = 0;
forward.Normalize();
//ワールド空間でのカメラのrigntを取得し、XZ成分を抽出したもので正規化
Vector3 right = Camera.main.transform.TransformDirection(Vector3.right);
right.y = 0;
right.Normalize();
//正規化されている方向ベクトルに入力とspeedをかける
forward *= Input.GetAxis ("Vertical") * speed * Time.deltaTime;
right *= Input.GetAxis ("Horizontal") * speed * Time.deltaTime;
//movementの更新
movement = right + forward;
}
void Move(){
//移動
playerRig.MovePosition (transform.position + movement);
}
void Turn(){
//動いていない場合、角度が取得できないので処理を除外
if(movement != Vector3.zero){
//ローカル空間における移動ベクトルを取得
Vector3 localMovement = transform.InverseTransformPoint(transform.position + movement);
//xz平面における原点(Player)と移動先の成す角度を取得
float angle = Mathf.Atan2(localMovement.z, localMovement.x);
//Z軸(0,0,1)との成す角度が知りたいので90°減算
angle -= Mathf.PI / 2;
//Quaternionは時計回りが正なので、得られた向きを逆転させる
angle *= -1;
//Rotateメドッドを使用するのでオイラーに変換
angle *= Mathf.Rad2Deg;
//ワールド座標でPlayerを回転
transform.Rotate(Vector3.up, angle, Space.World);
//回転
//transform.rotation = Quaternion.LookRotation (movement);
}
}
}

0 件のコメント:

コメントを投稿