优化第三人称相机
第三人称相机优化方案
概述
将相机控制逻辑从 Update() 迁移到 FixedUpdate() 以提高性能和稳定性。
优化原因
- 性能提升:
FixedUpdate()以固定时间间隔执行,减少不必要的计算 - 稳定性增强: 避免帧率波动对相机移动的影响
- 物理一致性: 与物理系统保持同步,减少抖动
核心代码
private void LateUpdate()
{
// 安全检查
if (followTarget == null || !isInitialized) return;
// 1. 视角控制反转参数设置
invertXValue = (invertX) ? -1 : 1;
invertYValue = (invertY) ? -1 : 1;
// 2. 视角旋转计算
// 水平视角控制 - 鼠标/手柄X轴控制Y轴旋转
rotationY += Input.GetAxis("Camera X") * rotationSpeed * invertYValue * Time.fixedDeltaTime;
// 垂直视角控制 - 鼠标/手柄Y轴控制X轴旋转
rotationX += Input.GetAxis("Camera Y") * rotationSpeed * invertXValue * Time.fixedDeltaTime;
// 限制垂直旋转角度范围
rotationX = Mathf.Clamp(rotationX, minVerticalAngle, maxVerticalAngle);
// 3. 计算目标旋转
targetRotation = Quaternion.Euler(rotationX, rotationY, 0);
// 4. 计算相机位置
// 焦点位置 = 目标位置 + 偏移量
var focusPosition = followTarget.position + new Vector3(frameOffset.x, frameOffset.y, 0);
// 目标位置 = 焦点位置 - 旋转后的距离向量
targetPosition = focusPosition - targetRotation * new Vector3(0, 0, distance);
// 5. 平滑插值更新相机变换
transform.position = Vector3.Lerp(transform.position, targetPosition, smoothSpeed * Time.fixedDeltaTime);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, smoothSpeed * Time.fixedDeltaTime);
}
| 参数 | 类型 | 说明 |
|---|---|---|
followTarget |
Transform | 相机跟随的目标对象 |
rotationSpeed |
float | 视角旋转速度 |
smoothSpeed |
float | 相机平滑移动速度 |
distance |
float | 相机与目标的距离 |
frameOffset |
Vector2 | 相机焦点偏移量 |
minVerticalAngle |
float | 垂直旋转最小角度 |
maxVerticalAngle |
float | 垂直旋转最大角度 |
完整代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
//摄像机跟随的目标
[SerializeField] Transform followTarget;
[SerializeField] float rotationSpeed = 1.5f;
//距离
[SerializeField] float distance;
//绕y轴的旋转角度——水平视角旋转
float rotationY;
//绕x轴的旋转角度——垂直视角旋转
float rotationX;
//限制rotationX幅度
[SerializeField] float minVerticalAngle = -20;
[SerializeField] float maxVerticalAngle = 45;
//框架偏移向量——摄像机位置视差偏移
[SerializeField] Vector2 frameOffset;
//视角控制反转
[Header("视角控制反转:invertX是否反转垂直视角,invertY是否反转水平视角")]
[SerializeField] bool invertX;
[SerializeField] bool invertY;
float invertXValue;
float invertYValue;
// 帧同步相关参数
[Header("帧同步设置")]
[SerializeField] float smoothSpeed = 10f; // 平滑插值速度
private Vector3 targetPosition;
private Quaternion targetRotation;
private bool isInitialized = false;
private void Start()
{
//隐藏光标
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
// 初始化目标位置和旋转
if (followTarget != null)
{
InitializeCamera();
}
}
private void InitializeCamera()
{
// 计算初始旋转
var initialRotation = Quaternion.Euler(rotationX, rotationY, 0);
var focusPosition = followTarget.position + new Vector3(frameOffset.x, frameOffset.y, 0);
// 设置初始位置和旋转
transform.position = focusPosition - initialRotation * new Vector3(0, 0, distance);
transform.rotation = initialRotation;
// 设置目标位置和旋转
targetPosition = transform.position;
targetRotation = transform.rotation;
isInitialized = true;
}
private void LateUpdate()
{
if (followTarget == null || !isInitialized) return;
//视角控制反转参数
invertXValue = (invertX) ? -1 : 1;
invertYValue = (invertY) ? -1 : 1;
//水平视角控制——鼠标(手柄)x轴控制rotationY
rotationY += Input.GetAxis("Camera X") * rotationSpeed * invertYValue * Time.fixedDeltaTime;
//垂直视角控制——鼠标(手柄)y轴控制rotationX
rotationX += Input.GetAxis("Camera Y") * rotationSpeed * invertXValue * Time.fixedDeltaTime;
//限制rotationX幅度
rotationX = Mathf.Clamp(rotationX, minVerticalAngle, maxVerticalAngle);
//视角旋转参量
//想要水平旋转视角,所以需要的参量为绕y轴旋转角度
targetRotation = Quaternion.Euler(rotationX, rotationY, 0);
//摄像机的焦点位置
var focusPosition = followTarget.position + new Vector3(frameOffset.x, frameOffset.y, 0);
//摄像机放在目标后面指定距离的位置
targetPosition = focusPosition - targetRotation * new Vector3(0, 0, distance);
// 使用平滑插值更新相机位置和旋转
transform.position = Vector3.Lerp(transform.position, targetPosition, smoothSpeed * Time.fixedDeltaTime);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, smoothSpeed * Time.fixedDeltaTime);
}
//水平方向的旋转,返回摄像机的水平旋转四元数。
public Quaternion PlanarRotation => Quaternion.Euler(0, rotationY, 0);
/// <summary>
/// 设置相机距离
/// </summary>
public void SetDistance(float newDistance)
{
distance = newDistance;
}
// 获取当前相机距离
public float GetDistance => distance;
/// <summary>
/// 设置平滑速度
/// </summary>
public void SetSmoothSpeed(float speed)
{
smoothSpeed = speed;
}
}
待扩展
- 添加相机碰撞检测系统
- 实现相机震动效果
- 支持多目标切换
- 添加相机FOV动态调整

浙公网安备 33010602011771号