Unity 摄像机漫游的代码。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SocialPlatforms;
public class CameraMove : MonoBehaviour
{
class CameraState
{
public float x, y, z;
public float pitch; //X 俯仰角
public float yaw; //Y 偏航角
public float roll; //Z 翻滚角
/// <summary>
/// 获取 目标Trans 的数值
/// </summary>
/// <param name="t"></param>
public void SetFromTransform(Transform t)
{
pitch = t.eulerAngles.x;
yaw = t.eulerAngles.y;
roll = t.eulerAngles.z;
x = t.position.x;
y = t.position.y;
z = t.position.z;
myCamera = t.GetComponent<Camera>();
}
/// <summary>
/// 计算移动和旋转
/// </summary>
/// <param name="target"></param>
/// <param name="positionLerpPct"></param>
/// <param name="rotationLerpPct"></param>
public void LerpTowards(CameraState target, float positionLerpPct, float rotationLerpPct)
{
yaw = Mathf.Lerp(yaw, target.yaw, rotationLerpPct);
pitch = Mathf.Lerp(pitch, target.pitch, rotationLerpPct);
roll = Mathf.Lerp(roll, target.roll, rotationLerpPct);
x = Mathf.Lerp(x, target.x, positionLerpPct);
y = Mathf.Lerp(y, target.y, positionLerpPct);
z = Mathf.Lerp(z, target.z, positionLerpPct);
}
/// <summary>
/// 操作
/// </summary>
/// <param name="translation"></param>
public void Translate(Vector3 translation)
{
//计算一个带有旋转角的位置
Vector3 rotatedTranslation = Quaternion.Euler(pitch, yaw, roll) * translation;
x += rotatedTranslation.x;
y += rotatedTranslation.y;
z += rotatedTranslation.z;
}
public void ReSet(Transform t)
{
pitch = yaw = roll = 0;
x = y = z = 0;
UpdateTransform(t);
}
/// <summary>
/// 更新
/// </summary>
/// <param name="t"></param>
public void UpdateTransform(Transform t)
{
t.eulerAngles = new Vector3(pitch, yaw, roll);
t.position = new Vector3(x, y, z);
}
private Camera myCamera;
public void ChangeFieldView(float temp)
{
myCamera.fieldOfView = Mathf.Clamp(myCamera.fieldOfView + temp, 20, 100);
}
}
CameraState targer = new CameraState();
CameraState interpolating = new CameraState();
/// <summary>
/// 平移的指数增强因子,可通过鼠标滚轮控制
/// </summary>
public float boost = 3.5f;
/// <summary>
/// 位置插值速度
/// </summary>
[Range(0.001f, 1f)]
public float positionLerpTime = 0.2f;
/// <summary>
/// 鼠标灵敏度
/// </summary>
public AnimationCurve mouseSensitivityCurve =
new AnimationCurve(new Keyframe(0f, 0.5f, 0f, 5f), new Keyframe(1f, 2.5f, 0f, 0f));
/// <summary>
/// 旋转插值速度
/// </summary>
public float rotationLerpTime = 0.01f;
/// <summary>
/// 反转Y轴
/// </summary>
public bool invertY = false;
void OnEnable()
{
targer.SetFromTransform(transform);
interpolating.SetFromTransform(transform);
}
Vector3 GetInputTranslationDirection()
{
Vector3 direction = new Vector3();
if (Input.GetKey(KeyCode.W))
{
direction += Vector3.forward;
}
if (Input.GetKey(KeyCode.A))
{
direction += Vector3.left;
}
if (Input.GetKey(KeyCode.S))
{
direction += Vector3.back;
}
if (Input.GetKey(KeyCode.D))
{
direction += Vector3.right;
}
if (Input.GetKey(KeyCode.Q))
{
direction += Vector3.down;
}
if (Input.GetKey(KeyCode.E))
{
direction += Vector3.up;
}
return direction;
}
private void Update()
{
if (EventSystem.current.IsPointerOverGameObject())
{
return;
}
Vector3 translation = Vector3.zero;
//锁鼠标
if (Input.GetMouseButtonDown(0))
{
Cursor.lockState = CursorLockMode.Locked;
}
// 解鼠标
if (Input.GetMouseButtonUp(0))
{
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
}
// 处理旋转
if (Input.GetMouseButton(0))
{
var mouseMovement = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y") * (invertY ? 1 : -1));
var mouseSensitivityFactor = mouseSensitivityCurve.Evaluate(mouseMovement.magnitude);
targer.yaw += mouseMovement.x * mouseSensitivityFactor;
targer.pitch += mouseMovement.y * mouseSensitivityFactor;
}
// 处理移动
//translation = GetInputTranslationDirection() * Time.deltaTime;
//boost += Input.mouseScrollDelta.y;
//translation *= Mathf.Pow(2.0f, boost);
//targer.Translate(translation);
interpolating.ChangeFieldView(Input.mouseScrollDelta.y);
var positionLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / positionLerpTime) * Time.deltaTime);
var rotationLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / rotationLerpTime) * Time.deltaTime);
interpolating.LerpTowards(targer, positionLerpPct, rotationLerpPct);
interpolating.UpdateTransform(transform);
}
public void ResetCamera()
{
targer.ReSet(transform);
interpolating.ReSet(transform);
}
}