Play模式下Unity相机初始位置异常偏移问题求助
问题:Unity相机初始位置在Play模式下莫名跳变
我有一个预制体相机,场景编辑模式下的transform.position为:
Scene:Vector3(-2.86999989,1.01999998,-0.810000002)
我在脚本中设置了对应的初始相机位置:
[SerializeField] private Vector3 initialCameraPosition = new Vector3(-2.86999989, 1.01999998, -0.810000002);
原本期望相机从该初始位置开始旋转,但进入Play模式后,相机的transform.position立即被覆盖为:
play:Vector3(-2.72023177,0.810079217,-1.23373544)
场景与Play模式下的位置差值:
X axis: 0.1498 Y axis: -0.2099 Z axis: -0.4237
挂载脚本的Target物体transform.position为Vector3(0,0,0),且已确认:
- 场景中仅使用1台相机
- 无其他脚本调用该相机
- 无其他设置影响相机
附上相关脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraController : MonoBehaviour { [SerializeField] private Transform target; [SerializeField] private Vector3 initialCameraPosition = new Vector3(3f, 1f, 2.5f); [SerializeField] private Vector3 initialCameraRotation = new Vector3(30f, 45f, 0f); public float sensitivity = 100f; // 旋转灵敏度 private float _yaw = 0f; // 当前水平旋转角度 private float _pitch = 0f; // 当前垂直旋转角度 private float minPitch = 5f; // 最小垂直角度 private float maxPitch = 90f; // 最大垂直角度 private Transform cameraObject; // 动态查找的相机对象 private float distanceFromTarget; // 原脚本遗漏的变量定义 void Start() { // 查找相机对象(未预先赋值时) cameraObject = Camera.main.transform; if (target == null) { Debug.LogError("未指定目标物体(Target)!"); } if (cameraObject == null) { Debug.LogError("场景中无相机!"); return; } // 设置初始位置与旋转角度 cameraObject.position = initialCameraPosition; cameraObject.rotation = Quaternion.Euler(initialCameraRotation); // 根据初始位置计算与目标的距离和旋转角度 Vector3 targetDirection = cameraObject.position - target.position; distanceFromTarget = targetDirection.magnitude; _yaw = initialCameraRotation.y; // 从初始旋转获取yaw值 _pitch = initialCameraRotation.x; // 从初始旋转获取pitch值 } void Update() { HandleInput(); // 限制pitch值范围 _pitch = Mathf.Clamp(_pitch, minPitch, maxPitch); // 围绕目标旋转相机 RotateCamera(); } private void HandleInput() { Vector2 inputDelta = Vector2.zero; // 移动端触摸输入 if (Input.touchCount > 0) { Touch touch = Input.GetTouch(0); inputDelta = touch.deltaPosition; } // 鼠标输入 else if (Input.GetMouseButton(0)) { inputDelta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")); } // 更新旋转角度 _yaw += inputDelta.x * sensitivity * Time.deltaTime; _pitch -= inputDelta.y * sensitivity * Time.deltaTime; } private void RotateCamera() { // 计算围绕目标的旋转角度 Quaternion rotation = Quaternion.Euler(_pitch, _yaw, 0f); Vector3 positionOffset = rotation * new Vector3(0, 0, -distanceFromTarget); // 设置相机位置与旋转角度 cameraObject.position = target.position + positionOffset; cameraObject.LookAt(target); } }
问题原因
核心问题是**Start()设置初始位置后,第一帧Update()执行的RotateCamera()直接覆盖了相机位置**:
Start()中你手动设置了相机初始位置,但同时用initialCameraRotation直接赋值给_yaw和_pitch- 你设置的初始位置
initialCameraPosition,和初始旋转initialCameraRotation对应的围绕目标点的位置并不匹配 - 进入Play模式后第一帧,
RotateCamera()会用_pitch和_yaw重新计算相机位置,这个新位置和你手动设置的初始位置不一致,导致跳变
解决方案
需要让_yaw和_pitch从初始相机位置反向计算,而非直接使用预设的旋转值,保证初始位置和旋转逻辑匹配。修改Start()方法中的旋转值计算部分:
void Start() { // ... 其他代码不变 // 设置初始位置 cameraObject.position = initialCameraPosition; // 根据初始位置计算与目标的距离 Vector3 targetDirection = cameraObject.position - target.position; distanceFromTarget = targetDirection.magnitude; // 从初始位置反向计算yaw和pitch,保证和初始位置匹配 _yaw = Mathf.Atan2(targetDirection.x, targetDirection.z) * Mathf.Rad2Deg; _pitch = Mathf.Asin(targetDirection.y / distanceFromTarget) * Mathf.Rad2Deg; _pitch = Mathf.Clamp(_pitch, minPitch, maxPitch); // 让相机朝向目标 cameraObject.LookAt(target); }
同时确保脚本中补充distanceFromTarget的变量声明:
private float distanceFromTarget;
修改后,初始位置会保持你设置的值,_yaw和_pitch由初始位置推导而来,第一帧RotateCamera()计算的位置和初始位置完全一致,不会出现跳变。
内容的提问来源于stack exchange,提问作者Cirill Parnò
相关产品推荐
相关产品推荐

