文章目录
前言
相机控制是游戏开发中至关重要的一部分,直接影响玩家在游戏中的视觉体验。在Unity中,我们可以通过自定义相机控制脚本来实现灵活、流畅的相机操作。本文将深入介绍一个基于Unity的相机控制脚本的设计与实现,包括鼠标旋转、键盘移动、滚轮缩放等功能。
一、概述
首先,让我们来了解一下相机控制脚本的主要目标。我们希望实现以下功能:
使用鼠标右键控制相机的旋转。
使用键盘控制相机的移动。
支持鼠标滚轮进行缩放。
平滑插值过渡相机状态,以确保相机移动的流畅性。
二、代码结构
using UnityEngine;
public class CameraCtrl : MonoBehaviour
{
private class CameraState
{
// 成员变量和方法在后文详细解释
}
// 主要成员变量和方法在后文详细解释
}
三、CameraState 类
3.1 相机状态信息
CameraState类负责保存相机的状态信息,包括旋转角度(yaw、pitch、roll)和位置(x、y、z)。
private class CameraState
{
public float yaw;
public float pitch;
public float roll;
public float x;
public float y;
public float z;
}
3.2 SetFromTransform 方法
SetFromTransform方法用于从一个Transform对象中提取旋转角度和位置,并将其应用到当前相机状态。
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;
}
3.3 Translate 方法
Translate方法用于根据输入的位移向量进行相机状态的平移。这里使用了旋转矩阵来转换位移向量,以考虑相机的旋转状态。
public void Translate(Vector3 translation)
{
Vector3 rotatedTranslation = Quaternion.Euler(pitch, yaw, roll) * translation;
x += rotatedTranslation.x;
y += rotatedTranslation.y;
z += rotatedTranslation.z;
}
3.4 LerpTowards 方法
LerpTowards方法实现了相机状态在两个状态之间的插值平滑过渡,包括旋转角度和位置。
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);
}
3.5 UpdateTransform 方法
UpdateTransform方法用于将相机状态应用到一个Transform对象,更新相机的旋转和位置信息。
public void UpdateTransform(Transform t)
{
t.eulerAngles = new Vector3(pitch, yaw, roll);
t.position = new Vector3(x, y, z);
}
3.6 主类 CameraCtrl
在主类CameraCtrl中,我们声明了相机状态的目标和插值状态,以及一些参数如加速度、插值时间等。在OnEnable方法中,我们初始化这两个状态,将其设置为当前相机的初始状态。
private CameraState m_TargetCameraState = new CameraState();
private CameraState m_InterpolatingCameraState = new CameraState();
public float boost = 3.5f;
public float positionLerpTime = 0.2f;
public AnimationCurve mouseSensitivityCurve = new AnimationCurve(new Keyframe(0f, 0.5f, 0f, 5f), new Keyframe(1f, 2.5f, 0f, 0f));
public float rotationLerpTime = 0.01f;
public bool invertY = false;
void OnEnable()
{
m_TargetCameraState.SetFromTransform(transform);
m_InterpolatingCameraState.SetFromTransform(transform);
}
3.7 输入处理
在Update方法中,我们处理用户的输入。通过检测鼠标右键的按下和松开,我们可以控制光标的锁定和显示。当右键按下时,光标被锁定,当右键松开时,光标解锁并显示。
if (Input.GetMouseButtonDown(1))
{
Cursor.lockState = CursorLockMode.Locked;
}
if (Input.GetMouseButtonUp(1))
{
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
}
3.8 鼠标旋转与键盘移动
当鼠标右键按下时,通过鼠标的移动来控制相机的旋转。使用mouseSensitivityCurve曲线调整鼠标灵敏度,并根据用户设置的invertY来控制是否反转垂直方向。
if (Input.GetMouseButton(1))
{
var mouseMovement = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y") * (invertY ? 1 : -1));
var mouseSensitivityFactor = mouseSensitivityCurve.Evaluate(mouseMovement.magnitude);
m_TargetCameraState.yaw += mouseMovement.x * mouseSensitivityFactor;
m_TargetCameraState.pitch += mouseMovement.y * mouseSensitivityFactor;
}
键盘输入控制相机的移动,通过GetInputTranslationDirection方法获取输入方向,然后根据输入方向和时间步长计算位移。按住Shift键时,移动速度加倍。
Vector3 translation = GetInputTranslationDirection() * Time.deltaTime;
if (Input.GetKey(KeyCode.LeftShift))
{
translation *= 10.0f;
}
m_TargetCameraState.Translate(translation);
3.9 缩放和插值平滑过渡
通过鼠标滚轮实现相机的缩放功能。滚轮滚动时,修改boost参数,然后通过插值计算得到新的移动增强因子,从而影响相机的位移。
boost += Input.mouseScrollDelta.y * 0.2f;
translation *= Mathf.Pow(2.0f, boost);
为了使相机运动更加平滑,使用帧率无关的插值方法,将当前相机状态平滑过渡到目标状态。通过计算插值的百分比,可以在指定的时间内到达目标的99%。
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);
m_InterpolatingCameraState.LerpTowards(m_TargetCameraState, positionLerpPct, rotationLerpPct);
m_InterpolatingCameraState.UpdateTransform(transform);
总结
通过这个相机控制脚本的设计与实现,我们实现了一个功能强大而灵活的相机控制器。通过细致的输入处理、插值平滑过渡以及参数调整,我们为游戏开发者提供了一个优雅的相机控制解决方案。希望这篇文章对Unity相机控制的学习和应用有所帮助。在实际项目中,可以根据需求进行修改和扩展,以适应不同类型的游戏场景。