Unity第三人称肩视角相机移动实现方案技术咨询
相机控制器开发求助
我在开发Unity相机控制器时进度缓慢,没法构思出可行的实现方案。目前已经通过新输入系统获取了鼠标输入并传入lookInput变量,还定义了mouseDelta但没用到,以下是修改后的代码,求技术帮助:
这是我在评论中提到的修改版本。
using UnityEngine.InputSystem; using UnityEngine; public class CameraController : MonoBehaviour { public InputActionAsset cameraInputs; private InputActionMap cameraMap; private InputAction lookAction; public float sensitivity = 10f; public Transform player; private Vector2 lookInput; public Vector3 defaultCameraPosition; private Vector3 initialOffset; private void Awake() { cameraMap = cameraInputs.FindActionMap("CameraMap"); lookAction = cameraMap.FindAction("Look"); lookAction.performed += OnLookPerformed; } private void Start() { transform.position = defaultCameraPosition; if (player == null) { initialOffset = transform.position - player.position; transform.LookAt(player.position); } Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; } private void Update() { Vector3 mouseDelta = new Vector3(-lookInput.y, lookInput.x, 0f) * sensitivity * Time.deltaTime; } private void LateUpdate() { RotateCamera(); } private void OnEnable() { cameraMap.Enable(); } private void OnDisable() { cameraMap.Disable(); } private void OnLookPerformed(InputAction.CallbackContext context) { lookInput = context.ReadValue<Vector2>(); } private void RotateCamera() { float yaw = lookInput.x * sensitivity * Time.deltaTime; float pitch = -lookInput.y * sensitivity * Time.deltaTime; player.Rotate(0f, yaw, 0f, Space.World); Vector3 currentRotation = player.transform.localEulerAngles; float newPitch = currentRotation.x + pitch; float maxPitch = 80f; newPitch = Mathf.Clamp(newPitch, -maxPitch, maxPitch); player.transform.localEulerAngles = new Vector3(newPitch, currentRotation.y, currentRotation.z); transform.LookAt(player.position); } }
问题分析与修复建议
空指针判断逻辑错误
Start方法里的if (player == null)写反了,应该是if (player != null),否则当player为空时执行player.position会触发空引用报错。相机旋转逻辑错误
当前代码把俯仰(上下拖动)和偏航(左右拖动)都应用在player上,会导致玩家模型跟着抬头低头,不符合常规第三人称相机逻辑。正确逻辑是:- 偏航(左右拖动)旋转player
- 俯仰(上下拖动)旋转相机本身,同时限制俯仰角度
initialOffset未被使用
应该在LateUpdate中通过这个变量维持相机与player的相对位置,避免相机位置漂移。mouseDelta变量冗余
当前Update里定义了mouseDelta但未使用,可直接删除,或在RotateCamera中复用该计算逻辑。
修复后的代码示例
using UnityEngine.InputSystem; using UnityEngine; public class CameraController : MonoBehaviour { public InputActionAsset cameraInputs; private InputActionMap cameraMap; private InputAction lookAction; public float sensitivity = 10f; public Transform player; private Vector2 lookInput; private Vector3 initialOffset; // 单独存储俯仰角度,避免欧拉角万向锁和角度范围异常 private float currentPitch = 0f; public float maxPitch = 80f; private void Awake() { cameraMap = cameraInputs.FindActionMap("CameraMap"); lookAction = cameraMap.FindAction("Look"); lookAction.performed += OnLookPerformed; } private void Start() { Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; if (player != null) { // 记录相机与玩家的初始相对偏移 initialOffset = transform.position - player.position; // 初始化俯仰角度并修正欧拉角0-360度范围问题 currentPitch = transform.localEulerAngles.x; if (currentPitch > 180f) currentPitch -= 360f; } } private void LateUpdate() { if (player == null) return; // 处理偏航:旋转玩家 float yaw = lookInput.x * sensitivity * Time.deltaTime; player.Rotate(Vector3.up, yaw, Space.World); // 处理俯仰:旋转相机并限制角度 currentPitch += -lookInput.y * sensitivity * Time.deltaTime; currentPitch = Mathf.Clamp(currentPitch, -maxPitch, maxPitch); // 更新相机位置和旋转 Quaternion playerYawRotation = Quaternion.Euler(0, player.eulerAngles.y, 0); transform.position = player.position + playerYawRotation * initialOffset; transform.rotation = playerYawRotation * Quaternion.Euler(currentPitch, 0, 0); } private void OnEnable() { cameraMap.Enable(); } private void OnDisable() { cameraMap.Disable(); } private void OnLookPerformed(InputAction.CallbackContext context) { lookInput = context.ReadValue<Vector2>(); } }
关键优化说明
- 分离玩家旋转(偏航)和相机旋转(俯仰),符合常规第三人称视角逻辑
- 使用独立变量存储俯仰角度,避免欧拉角的万向锁问题和角度范围异常
- 通过玩家旋转更新相机位置,维持初始相对距离和方向
- 修复空指针判断逻辑,避免运行时错误
内容的提问来源于stack exchange,提问作者user20658958
相关产品推荐
相关产品推荐

