You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 异常:
    if (pivotAngle > 180) pivotAngle -= 360;
    
    让代码中的旋转变量与场景中pivot物体的初始角度保持一致,避免启动时旋转跳变。
  • 稳定旋转速度计算:将旋转逻辑中的/ 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:50:46