概要
Unityでデバックとかする時に使ってる移動・回転をするためのカメラのスクリプトです。
ふと忘れたり、スクリプトが色々な所にあったりするので備忘録を兼ねてQiitaに公開したい。
CameraMover.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SocialPlatforms;
public class CameraMover : MonoBehaviour
{
// WASD:前後左右の移動
// QE:上昇・降下
// 右ドラッグ:カメラの回転
// 左ドラッグ:前後左右の移動
// スペース:カメラ操作の有効・無効の切り替え
// P:回転を実行時の状態に初期化する
//カメラの移動量
[SerializeField, Range(0.1f, 10.0f)]
private float _positionStep = 2.0f;
//マウス感度
[SerializeField, Range(30.0f, 150.0f)]
private float _mouseSensitive = 90.0f;
//カメラ操作の有効無効
private bool _cameraMoveActive = true;
//カメラのtransform
private Transform _camTransform;
//マウスの始点
private Vector3 _startMousePos;
//カメラ回転の始点情報
private Vector3 _presentCamRotation;
private Vector3 _presentCamPos;
//初期状態 Rotation
private Quaternion _initialCamRotation;
//UIメッセージの表示
private bool _uiMessageActiv;
void Start ()
{
_camTransform = this.gameObject.transform;
//初期回転の保存
_initialCamRotation = this.gameObject.transform.rotation;
}
void Update () {
CamControlIsActive(); //カメラ操作の有効無効
if (_cameraMoveActive)
{
ResetCameraRotation(); //回転角度のみリセット
CameraRotationMouseControl(); //カメラの回転 マウス
CameraSlideMouseControl(); //カメラの縦横移動 マウス
CameraPositionKeyControl(); //カメラのローカル移動 キー
}
}
//カメラ操作の有効無効
public void CamControlIsActive()
{
if (Input.GetKeyDown(KeyCode.Space))
{
_cameraMoveActive = !_cameraMoveActive;
if (_uiMessageActiv == false)
{
StartCoroutine(DisplayUiMessage());
}
Debug.Log("CamControl : " + _cameraMoveActive);
}
}
//回転を初期状態にする
private void ResetCameraRotation()
{
if(Input.GetKeyDown(KeyCode.P))
{
this.gameObject.transform.rotation = _initialCamRotation;
Debug.Log("Cam Rotate : " + _initialCamRotation.ToString());
}
}
//カメラの回転 マウス
private void CameraRotationMouseControl()
{
if (Input.GetMouseButtonDown(0))
{
_startMousePos = Input.mousePosition;
_presentCamRotation.x = _camTransform.transform.eulerAngles.x;
_presentCamRotation.y = _camTransform.transform.eulerAngles.y;
}
if (Input.GetMouseButton(0))
{
//(移動開始座標 - マウスの現在座標) / 解像度 で正規化
float x = (_startMousePos.x - Input.mousePosition.x) / Screen.width;
float y = (_startMousePos.y - Input.mousePosition.y) / Screen.height;
//回転開始角度 + マウスの変化量 * マウス感度
float eulerX = _presentCamRotation.x + y * _mouseSensitive;
float eulerY = _presentCamRotation.y + x * _mouseSensitive;
_camTransform.rotation = Quaternion.Euler(eulerX, eulerY, 0);
}
}
//カメラの移動 マウス
private void CameraSlideMouseControl()
{
if (Input.GetMouseButtonDown(1))
{
_startMousePos = Input.mousePosition;
_presentCamPos = _camTransform.position;
}
if (Input.GetMouseButton(1))
{
//(移動開始座標 - マウスの現在座標) / 解像度 で正規化
float x = (_startMousePos.x - Input.mousePosition.x) / Screen.width;
float y = (_startMousePos.y - Input.mousePosition.y) / Screen.height;
x = x * _positionStep;
y = y * _positionStep;
Vector3 velocity = _camTransform.rotation * new Vector3(x, y, 0);
velocity = velocity + _presentCamPos;
_camTransform.position = velocity;
}
}
//カメラのローカル移動 キー
private void CameraPositionKeyControl()
{
Vector3 campos = _camTransform.position;
if (Input.GetKey(KeyCode.D)) { campos += _camTransform.right * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.A)) { campos -= _camTransform.right * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.E)) { campos += _camTransform.up * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.Q)) { campos -= _camTransform.up * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.W)) { campos += _camTransform.forward * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.S)) { campos -= _camTransform.forward * Time.deltaTime * _positionStep; }
_camTransform.position = campos;
}
//UIメッセージの表示
private IEnumerator DisplayUiMessage()
{
_uiMessageActiv = true;
float time = 0;
while (time < 2)
{
time = time + Time.deltaTime;
yield return null;
}
_uiMessageActiv = false;
}
void OnGUI()
{
if (_uiMessageActiv == false) { return; }
GUI.color = Color.black;
if (_cameraMoveActive == true)
{
GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height - 30, 100, 20), "カメラ操作 有効");
}
if (_cameraMoveActive == false)
{
GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height - 30, 100, 20), "カメラ操作 無効");
}
}
}
使い方
1.CameraMover という名前でC#のスクリプトを作成。
2.初期のテンプレートを消して、上記のスクリプトをコピペする。
3.CameraMover をカメラにアタッチする。
※自分の場合は、空のゲームオブジェクトを作って「CameraRig」とか適当な名前つけて「CameraRig」にCameraMoverをアタッチします。
その後、CameraRigの子にカメラのゲームオブジェクトを設定して、カメラのトランスフォームを初期化しています。
操作方法
WASD:前後左右の移動
QE:上昇・降下
右ドラッグ:カメラの回転
左ドラッグ:前後左右の移動
スペース:カメラ操作の有効・無効の切り替え
P:回転を実行時の状態に初期化する。
スクリプト解説
CameraRotationMouseControl()
private void CameraRotationMouseControl()
{
if (Input.GetMouseButtonDown(0))
{
_startMousePos = Input.mousePosition;
_presentCamRotation.x = _camTransform.transform.eulerAngles.x;
_presentCamRotation.y = _camTransform.transform.eulerAngles.y;
}
if (Input.GetMouseButton(0))
{
//(移動開始座標 - マウスの現在座標) / 解像度 で正規化
float x = (_startMousePos.x - Input.mousePosition.x) / Screen.width;
float y = (_startMousePos.y - Input.mousePosition.y) / Screen.height;
//回転開始角度 + マウスの変化量 * マウス感度
float eulerX = _presentCamRotation.x + y * _mouseSensitive;
float eulerY = _presentCamRotation.y + x * _mouseSensitive;
_camTransform.rotation = Quaternion.Euler(eulerX, eulerY, 0);
}
}
やってる事はクリックした時に「現在の回転の姿勢」と「クリックをした場所」を保存して…
その値を元にクリックした場所からの変化量をつかって、現在の姿勢に対して追加の回転を計算。
それを新規に現在の回転に適用しています。
やってる事はシンプルなんですが…ここにたどり着くまで自分はけっこうかかりました…
例えば「マウスの現在地を常に現在の回転」にすると、回転できる角度が制限されたり、UIが操作しづらかったり結構不便だったりします。
なので「クリックしてる時だけ変化して欲しい」という事になるのですが「現在の姿勢」と「マウスの変化量を足した次の姿勢」を表現するのが結構厄介です。
適当にやっても回る事は回るのですが、雑にやるとZ成分がまざって傾いたカメラになったりします。
Z成分が入ると非常に不便なので… _camTransform.rotation = Quaternion.Euler(eulerX, eulerY, 0); この行が重要だったりします。
CameraLocalposKeyControl()
//カメラのローカル移動 キー
private void CameraLocalposKeyControl()
{
Vector3 campos = _camTransform.position;
if (Input.GetKey(KeyCode.D)) { campos += _camTransform.right * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.A)) { campos -= _camTransform.right * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.E)) { campos += _camTransform.up * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.Q)) { campos -= _camTransform.up * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.W)) { campos += _camTransform.forward * Time.deltaTime * _positionStep; }
if (Input.GetKey(KeyCode.S)) { campos -= _camTransform.forward * Time.deltaTime * _positionStep; }
_camTransform.position = campos;
}
基本的には**「this.Gameobject.transform」の forward up right を足してるだけです。
Time.deltaTimeを掛けて1フレームあたりの変化量に調整して、変化の倍率をかけてるだけです。
これだけで「現在の姿勢に対する前後左右上下に移動」**できます。
カメラを移動しながら撮影したい。
【Unity】Unityでスクリーンショットを撮る時に必要なTipsまとめ
上記を参考にしてみてください。キャラクターを撮影するプロジェクトが作れます。
※キー設定が被ってるのでよしなに。