【Unity3D】回転の制限とカメラついて
FPSやTPSのゲームではカメラの回転に制限がかかっています。
ですがカメラをtransdorm.Rotate()でただ回転させるだけだと、上下への回転(x軸に対する回転)が一回転しておかしなことになってしまいます。
今回はこれを解決する
「回転に制限のついたカメラ」を作ります。
手っ取り早く動かしたい人は完成スクリプトコピペしてください
前提
やりたいこと自体はこのイメージです。
仕様的な内容
マウスの移動に合わせ、上下に制限つき、左右に制限なしで回転するカメラ
を作ります。以下要素
- 入力はマウスの移動から取る
- X軸をもとに回転する⇒上下に回転の制限をつける
- Y軸をもとに回転する⇒回転制限なし
- 回転の制限となる値はエディターから設定する
用意するもの
- カメラオブジェクト
- CameraController.csスクリプト
- 地面や配置物⇒カメラがどのように回転しているか把握するため
X軸とY軸それぞれを回転させる
とりあえず回転させます。
void Update() { var _inputX = Input.GetAxis("Mouse X"); var _inputY = Input.GetAxis("Mouse Y"); transform.Rotate(_inputY, _inputX, 0); }
マウスのXの移動量を_inputXに、Yの移動量を_inputYに代入し
transform.Rotateで回転させていますが、
このままだとY軸の回転が常にワールド基準のY軸を元にした回転ではなくなるため、
X軸の回転とY軸の回転の基準をそれぞれ分ける必要があります。
void Update() { var _inputX = Input.GetAxis("Mouse X"); var _inputY = Input.GetAxis("Mouse Y"); //X軸回転 var localAngle = transform.localEulerAngles; localAngle.x += _inputY; transform.localEulerAngles = localAngle; //Y軸回転 var angle = transform.eulerAngles; angle.y += _inputX; transform.eulerAngles = angle; }
transform.Rotateではなく、transformの回転をx,y,zの値で表すlocalEulerAnglesとeulerAnglesの値を取得し、
そのx,yの値を変更してから代入しなおすことで回転させています。
localEulerAnglesはオブジェクト自体がもつ基準による回転情報で、
eulerAnglesはワールド基準による回転情報です。
回転に制限をつける
エディター上の回転の値を、transform.rotation.xのように取得することはできません。
transform.rotationはQuaternion(四元数)で表現されています。
今回は四元数ではなくx,y,zの値で表現されたEulerAnglesなどがあるのでこれを角度制限のフックに使います。
void Update() { var _inputX = Input.GetAxis("Mouse X"); var _inputY = Input.GetAxis("Mouse Y"); float maxLimit = 60, minLimit = 360 - maxLimit; //X軸回転 var localAngle = transform.localEulerAngles; localAngle.x += _inputY; if (localAngle.x > maxLimit && localAngle.x < 180) localAngle.x = maxLimit; if (localAngle.x < minLimit && localAngle.x > 180) localAngle.x = minLimit; transform.localEulerAngles = localAngle; //Y軸回転 var angle = transform.eulerAngles; angle.y += _inputX; transform.eulerAngles = angle; }
eulerAnglesとlocalEulerAnglesのx,y,zは時計回りに0°~360°の値になっているので180°前後の条件も付けています。
完成スクリプト
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraController : MonoBehaviour { [SerializeField] float viewAngle;//エディター上で60を入力 float _inputX, _inputY; void Update() { _inputX = Input.GetAxis("Mouse X"); _inputY = Input.GetAxis("Mouse Y"); Rotate(_inputX, _inputY, viewAngle); } void Rotate(float _inputX,float _inputY,float limit) { float maxLimit = limit, minLimit = 360 - maxLimit; //X軸回転 var localAngle = transform.localEulerAngles; localAngle.x += _inputY; if (localAngle.x > maxLimit && localAngle.x < 180) localAngle.x = maxLimit; if (localAngle.x < minLimit && localAngle.x > 180) localAngle.x = minLimit; transform.localEulerAngles = localAngle; //Y軸回転 var angle = transform.eulerAngles; angle.y += _inputX; transform.eulerAngles = angle; } }