WSADの移動方向、マウスの右ボタンの回転角度、ズームを実現するスクロールホイールを実現します。
その前に、いくつかのわかりにくい点を明確にしましょう。
1: Transform.forwardは、Transform コンポーネントの Vector3 型属性で、ワールド座標系におけるゲームオブジェクトの向き、つまり「正面方向」を表し、その値は (0,0,1) です。オブジェクトの方向を表します。X 軸方向は通常、移動、回転、光線検出などのシナリオなど、ゲーム オブジェクトが移動する方向を計算するために使用されます。
2: Transform.Rightの数式は (1, 0, 0) です。オブジェクトの X 軸方向、またはその右方向を表します。
これらはすべて単位ベクトルであり、通常は方向の計算にのみ使用されることに注意してください。
3:Input.GetAxis("水平")とInput.GetAxis("垂直")、input.GetAxis("マウスX")
それぞれ水平入力と垂直入力を取得する関数で、現在の水平方向の入力状態を-1から1までの浮動小数点数で返します。
たとえば、Input.GetAxis("Mouse X")
水平方向のマウスの動きを浮動小数点数で返します。マウスが右に移動すると正の値が返され、マウスが左に移動すると負の値が返されます。マウスが動いていない場合は 0 を返します
Input.GetAxis("Mouse ScrollWheel")、前方スクロールは正の数、後方スクロールは負の数
4: オイラー角と四元数
一体の回転はオイラー角を利用するもので、オイラー角とは3軸を基準とし、物体の回転状態を異なる軸(通常はXYZ、ZYX、ZXYなど)の周りの回転角度で表します。回転シーケンス。ただし、オイラー角にはジンバル ロックの問題が発生します。つまり、特定のケースでは 2 つの軸の回転が一致し、回転計算が異常になります。
クォータニオンは、クォータニオンの定義と操作によって回転を実現しますが、クォータニオンは実際には 1 つの実部と 3 つの虚数部を含む四元数です。これらは、ジンバル ロックの問題を回避するためにオイラー角とは異なる方法で定義されており、回転順序は回転結果に影響しません。クォータニオンは補間演算を通じてスムーズな回転を実現することもできるため、連続回転が必要な状況に適しています。
コードを 3 つの部分に分割しました
最初のモジュールは前後左右を制御する WSAD で、このセクションは比較的単純で、V3 タイプの移動方向を直接定義し、Translate を使用します。
2 番目のモジュールは、QE を使用して上下の画角を制御し、変数 upDown を定義し、ボタンを押すたびに 1 を変更し、その位置をカメラの位置に直接割り当てます。
3 番目のモジュールは、マウスの右ボタンを使用して回転し、2 つの回転ベクトル、rotateX、rotateY、Y 方向の回転制限 minAngle と maxAngle を設定し、ベクトルと速度をカメラのオイラー角に追加します。
問題があります。最初にデバッグを開始したとき、初めてマウスの右ボタンをクリックして回転すると、画面が飛び続けました。最終的に、GPT の助けを借りて、問題は解決されました。愛のGPT
using UnityEngine;
public class CameraController : MonoBehaviour
{
//WSAD相机移动速度
public float moveSpeed = 1.0f;
//相机当前移动方向
private Vector3 moveDirection;
//QE相机的目标高度
private float upDistance;
public float upSpeed = 0.2f;
//鼠标右键控制旋转
private float rotateX,rotateY;
public float sensitivity =0.5f;
//控制鼠标在Y方向上的限值
public float minAngle = -90f;
public float maxAngle = 90f;
//记录之前的欧拉角,避免跳屏
private Vector3 currentRotation,lastPosition;
//鼠标滚轮控制缩放
public float zoomSpeed = 10f;
private float zoomDistance = 0f;
private void Start()
{
currentRotation = transform.eulerAngles;
}
void Update()
{
// 使用WSAD控制相机前后左右移动比较简单,直接获取当前的移动方向,然后使用Translate移动即可
{
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
transform.Translate(moveDirection * moveSpeed * Time.deltaTime);
}
//使用QE控制相机的上下,使用unDown参数进行单位变化
{
if (Input.GetKey(KeyCode.Q))
{
upDistance -= upSpeed * Time.deltaTime;
transform.Translate(transform.up * upDistance, Space.World);
}
else if(Input.GetKeyUp(KeyCode.Q))
{
upDistance = 0;
}
if (Input.GetKey(KeyCode.E))
{
upDistance += upSpeed * Time.deltaTime;
transform.Translate(transform.up * upDistance, Space.World);
}
else if(Input.GetKeyUp(KeyCode.E))
{
upDistance = 0;
}
}
//使用鼠标右键来控制相机旋转
//Mouse X,向右移动返回正值,Mouse Y,向上移动鼠标为正值
{
if (Input.GetMouseButtonDown(1))
{
// 记录当前的欧拉角
//currentRotation = transform.eulerAngles;
//记录鼠标位置
lastPosition = Input.mousePosition;
}
if (Input.GetMouseButton(1))
{
//设置偏移量
Vector3 offset = Input.mousePosition - lastPosition;
rotateX += offset.x * sensitivity;
rotateY -= offset.y * sensitivity;
//给Y方向的旋转加上限值函数
rotateY = Mathf.Clamp(rotateY, minAngle, maxAngle);
//改变当前的欧拉角
transform.eulerAngles = new Vector3(rotateY, rotateX, 0f);
// 将保存的欧拉角重新赋值回去
transform.eulerAngles += currentRotation;
lastPosition = Input.mousePosition;
}
}
//使用滚轮来控制物体的缩放
{
//获取滚轮的滚动幅度和方向
zoomDistance += Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
//使用限值函数来限定缩放的范围
zoomDistance = Mathf.Clamp(zoomDistance, -10f, 10f);
//最后定位
transform.position = transform.position + transform.forward * Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
}
}
}
コードを直接コピーし、カメラに掛けて実行してください。