Unity游戏启动时相机莫名上移问题求助
相机控制启动时莫名上移问题排查与修复
我参照教程实现相机控制,启动游戏时相机出现异常上移。已检查代码行与Transform设置,手动给主相机添加X轴旋转仅能勉强改善,效果仍不理想。
相机控制代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace BARR3TT { public class CameraHandler : MonoBehaviour { public Transform targetTransform; public Transform cameraTransform; public Transform cameraPivotTransform; private Transform myTransform; private Vector3 cameraTransformPosition; private LayerMask ignoreLayers; private Vector3 cameraFollowVelocity = Vector3.zero; public static CameraHandler singleton; public float lookSpeed = 0.1f; public float followSpeed = 0.1f; public float pivotSpeed = 0.03f; private float targetPosition; private float defaultPosition; private float lookAngle; private float pivotAngle; public float minimumPivot = -35; public float maximumPivot = 35; private float cameraSphereRadius = 0.2f; public float cameraColisionOffset = 0.2f; public float minimumColisionOffset = 0.2f; private void Awake() { singleton = this; myTransform = transform; defaultPosition = cameraTransform.localPosition.z; ignoreLayers = ~(1 << 8 | 1 << 9 << 10); } public void FollowTarget(float delta) { Vector3 targetPosition = Vector3.SmoothDamp(myTransform.position, targetTransform.position, ref cameraFollowVelocity, delta / followSpeed); myTransform.position = targetPosition; HandleCameraCollision(delta); } public void HandleCameraRotation(float delta, float mouseXInput, float mouseYInput) { lookAngle += (mouseXInput * lookSpeed) / delta; pivotAngle -= (mouseYInput * pivotSpeed) / delta; pivotAngle = Mathf.Clamp(pivotAngle, minimumPivot, maximumPivot); Vector3 rotation = Vector3.zero; rotation.y = lookAngle; Quaternion targetRotation = Quaternion.Euler(rotation); myTransform.rotation = targetRotation; rotation = Vector3.zero; rotation.x = pivotAngle; targetRotation = Quaternion.Euler(rotation); cameraPivotTransform.localRotation = targetRotation; } private void HandleCameraCollision(float delta) { targetPosition = defaultPosition; RaycastHit hit; Vector3 direction = cameraTransform.position - cameraPivotTransform.position; direction.Normalize(); if(Physics.SphereCast(cameraPivotTransform.position, cameraSphereRadius, direction, out hit ,Mathf.Abs(targetPosition))) { float dis = Vector3.Distance(cameraPivotTransform.position, hit.point); targetPosition = -(dis - cameraColisionOffset); } if(Mathf.Abs(targetPosition)<minimumColisionOffset) { targetPosition = -minimumColisionOffset; } cameraTransformPosition.z = Mathf.Lerp(cameraTransform.localPosition.z, targetPosition, delta / 0.2f); cameraTransform.localPosition = cameraTransformPosition; } } }
问题修复方案
- 初始化相机位置变量:在
Awake方法中添加cameraTransformPosition = cameraTransform.localPosition;,避免初始时用默认Vector3.zero覆盖相机原本的x/y轴位置,导致位置偏移。 - 修正LayerMask位运算错误:原代码中
1 << 9 << 10是错误的位运算逻辑,应改为1 << 10,正确的LayerMask代码为:
错误的位运算会导致射线检测错误地忽略/检测不该处理的层,引发碰撞逻辑异常。ignoreLayers = ~(1 << 8 | 1 << 9 | 1 << 10); - 同步初始旋转角度:在
Awake中添加pivotAngle = cameraPivotTransform.localEulerAngles.x;,同时处理EulerAngle的0-360转成-180-180区间,避免角度 clamp 异常:
让代码中的旋转变量与场景中pivot物体的初始角度保持一致,避免启动时旋转跳变。if (pivotAngle > 180) pivotAngle -= 360; - 稳定旋转速度计算:将旋转逻辑中的
/ delta改为* delta,保证不同帧率下旋转速度一致,同时适当调高速度参数(比如lookSpeed改为10,pivotSpeed改为8),修正后的旋转代码:lookAngle += mouseXInput * lookSpeed * delta; pivotAngle -= mouseYInput * pivotSpeed * delta;
修正后的完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace BARR3TT { public class CameraHandler : MonoBehaviour { public Transform targetTransform; public Transform cameraTransform; public Transform cameraPivotTransform; private Transform myTransform; private Vector3 cameraTransformPosition; private LayerMask ignoreLayers; private Vector3 cameraFollowVelocity = Vector3.zero; public static CameraHandler singleton; public float lookSpeed = 10f; public float followSpeed = 0.1f; public float pivotSpeed = 8f; private float targetPosition; private float defaultPosition; private float lookAngle; private float pivotAngle; public float minimumPivot = -35; public float maximumPivot = 35; private float cameraSphereRadius = 0.2f; public float cameraColisionOffset = 0.2f; public float minimumColisionOffset = 0.2f; private void Awake() { singleton = this; myTransform = transform; defaultPosition = cameraTransform.localPosition.z; // 初始化相机位置变量 cameraTransformPosition = cameraTransform.localPosition; // 修正LayerMask位运算 ignoreLayers = ~(1 << 8 | 1 << 9 | 1 << 10); // 同步初始pivot角度并处理区间转换 pivotAngle = cameraPivotTransform.localEulerAngles.x; if (pivotAngle > 180) pivotAngle -= 360; } public void FollowTarget(float delta) { Vector3 targetPosition = Vector3.SmoothDamp(myTransform.position, targetTransform.position, ref cameraFollowVelocity, followSpeed * delta); myTransform.position = targetPosition; HandleCameraCollision(delta); } public void HandleCameraRotation(float delta, float mouseXInput, float mouseYInput) { // 修正旋转速度计算 lookAngle += mouseXInput * lookSpeed * delta; pivotAngle -= mouseYInput * pivotSpeed * delta; pivotAngle = Mathf.Clamp(pivotAngle, minimumPivot, maximumPivot); Vector3 rotation = Vector3.zero; rotation.y = lookAngle; Quaternion targetRotation = Quaternion.Euler(rotation); myTransform.rotation = targetRotation; rotation = Vector3.zero; rotation.x = pivotAngle; targetRotation = Quaternion.Euler(rotation); cameraPivotTransform.localRotation = targetRotation; } private void HandleCameraCollision(float delta) { targetPosition = defaultPosition; RaycastHit hit; Vector3 direction = cameraTransform.position - cameraPivotTransform.position; direction.Normalize(); if(Physics.SphereCast(cameraPivotTransform.position, cameraSphereRadius, direction, out hit, Mathf.Abs(targetPosition), ignoreLayers)) { float dis = Vector3.Distance(cameraPivotTransform.position, hit.point); targetPosition = -(dis - cameraColisionOffset); } if(Mathf.Abs(targetPosition)<minimumColisionOffset) { targetPosition = -minimumColisionOffset; } cameraTransformPosition.z = Mathf.Lerp(cameraTransform.localPosition.z, targetPosition, delta / 0.2f); cameraTransform.localPosition = cameraTransformPosition; } } }
内容的提问来源于stack exchange,提问作者Barrett
相关产品推荐
相关产品推荐

