Unityでの空間移動用のスクリプト

Unityでプレイヤーが空間内を自由に移動や回転できるようにするスクリプトを紹介します。

(前置きですが)そもそも、三次元空間内における移動と回転は、3つの軸それぞれについて可能です。
図で説明すると以下のようです。

移動については、自分の正面方向を基準にして前後、左右、および上下への平行移動が可能です。
回転は、軸ごとに Yaw, Pitch, および Roll と呼ばれる回転が可能です。

上記の平行移動と回転を行ない、空中を飛行できるシンプルなスクリプトをここでは紹介します。
(これは空間を飛ぶように移動するもので、地面に沿って歩くようなものではありません)

方法

まずプレイヤー用のオブジェクトを作ります。
– メニューから GameObject > 3D Object > Cube などを選びます。
– このプレイヤーオブジェクトに Rigidbody コンポーネントを追加します。
(オブジェクトを選択し、Inspectorから Add Component > Physics > Rigidbody を選択)
– Rigidbodyの Use Gravity はオフにします。

カメラの設定
– 作ったプレイヤーオブジェクトの中に Main Camera を移動させます(下図のような状態)。
– Camera の Position は全て0にしておきましょう。

C# スクリプトの作成
– Project ウィンドウ内で右クリック > Create > C# Script を選択し、新規C#スクリプトを作成する。
– スクリプトのファイル名は MovementController として下さい。
– スクリプトの編集画面を開いて、この記事の末尾にあるコードに置き換えて下さい。

次にインプット(入力ボタン)の編集を行います。
– メニューから Edit > Project Settings > Input で InputManager を開きます。
Axes の中に Yaw や Pitch や Roll の項目がない場合は、それを作成します。やり方は、
– まず Size の値を現在の値より3だけ大きい値に変更します。
– 3つ分の項目が末尾に同じ名前で増えるので、これら3つを編集します。
この画像のような設定で、増えた3つの項目をそれぞれ Yaw, Pitch, Roll 用の設定にします。

以上で準備は完了です。ゲームを開始するとキー押しによってプレイヤーの移動が可能です。

使い方

矢印キーと左右のシフトキーで回転、U,J,H,K,Y,I で平行移動できます。
W,S,A,D,Q,R でも回転できます。

キーの変更は、回転についてはメニューから Edit > Project Settings > Input で InputManager を開き、Yaw, Pitch, Roll の各項目内の Negative Button や Positive Button を変えると変更できます。
平行移動についてはスクリプト内でハードコードされているので、スクリプトを直接書き換えて下さい。
62行目あたりからの KeyCode.U などの箇所を KeyCode.X などとすれば X キーでの入力に変更できます。

空間内に他の物体が無いと自己移動がわかりにくいので、適当に物体を配置してみると移動していることがわかりやすくなると思います(下図では Cube 1 というやつ)。

インスペクターに表示されているチェックボックス(CanMoveなど)は、特定の移動をできないようにするための設定です。
CanMove をオフにするとあらゆる移動や回転が不可能になります。
それ以外については、特定の移動や回転だけを選択的に不可能にするためのものです。
前後左右には移動できるが上下には移動できないようにしたい、などの場合に利用して下さい。

参考ページ

Unity 3D Code Snippet – Flight Script
https://keithmaggio.wordpress.com/2011/07/01/unity-3d-code-snippet-flight-script/

MovementController スクリプト

using UnityEngine;
using System.Collections;

public class MovementController : MonoBehaviour {

	public bool CanMove = true;
	public bool CanMoveForward = true;
	public bool CanMoveBack = true;
	public bool CanMoveLeft = true;
	public bool CanMoveRight = true;
	public bool CanMoveUp = true;
	public bool CanMoveDown = true;
	public bool CanRotateYaw = true;
	public bool CanRotatePitch = true;
	public bool CanRotateRoll = true;

	public float MovementSpeed = 100f;
	public float RotationSpeed = 100f;

	private bool canTranslate;
	private bool canRotate;

	void Start() {
		canTranslate = CanRotateYaw || CanRotatePitch || CanRotateRoll;
		canRotate = CanMoveForward || CanMoveBack || CanMoveRight || CanMoveLeft || CanMoveUp || CanMoveDown;
	}
	
	void Update() {
		
	}

	void FixedUpdate() {
		if( CanMove ) {
			UpdatePosition();
		}
	}

	void UpdatePosition() {
		// Rotation
		if( canRotate ) {
			Quaternion AddRot = Quaternion.identity;
			float yaw = 0;
			float pitch = 0;
			float roll = 0;
			if( CanRotateYaw ) {
				yaw = Input.GetAxis( "Yaw" ) * ( Time.fixedDeltaTime * RotationSpeed );
			}
			if( CanRotatePitch ){
				pitch = Input.GetAxis( "Pitch" ) * ( Time.fixedDeltaTime * RotationSpeed );
			}
			if( CanRotateRoll ){
				roll = Input.GetAxis( "Roll" ) * ( Time.fixedDeltaTime * RotationSpeed );
			}
			AddRot.eulerAngles = new Vector3( -pitch, yaw, -roll );
			GetComponent<Rigidbody>().rotation *= AddRot;
		}

		// Translation
		if( canTranslate ){
			// Check key input
			int[] input = new int[ 6 ]; // Forward, Back, Left, Right, Up, Down
			if( CanMoveForward && Input.GetKey( KeyCode.U ) ) {
				input[ 0 ] = 1;
			} else if( CanMoveBack && Input.GetKey( KeyCode.J ) ) {
				input[ 1 ] = 1;
			}
			if( CanMoveLeft && Input.GetKey( KeyCode.H ) ) {
				input[ 2 ] = 1;
			} else if( CanMoveRight && Input.GetKey( KeyCode.K ) ) {
				input[ 3 ] = 1;
			}
			if( CanMoveUp && Input.GetKey( KeyCode.Y ) ) {
				input[ 4 ] = 1;
			} else if( CanMoveDown && Input.GetKey( KeyCode.I ) ) {
				input[ 5 ] = 1;
			}
			int numInput = 0;
			for( int i = 0; i < 6; i++ ){
				numInput += input[ i ];
			}
			// Add velocity to the gameobject
			float curSpeed = numInput > 0 ? MovementSpeed : 0;
			Vector3 AddPos = input[ 0 ] * Vector3.forward + input[ 2 ] * Vector3.left + input[ 4 ] * Vector3.up
				+ input[ 1 ] * Vector3.back + input[ 3 ] * Vector3.right + input[ 5 ] * Vector3.down;
			AddPos = GetComponent<Rigidbody>().rotation * AddPos;
			GetComponent<Rigidbody>().velocity = AddPos * ( Time.fixedDeltaTime * curSpeed );
		}
	}

}

コメント