Unity无人机跟随玩家及射灯平滑旋转异常问题排查
Unity无人机跟随与射灯对准问题修复
需求
无人机始终保持在玩家后方固定距离,无论自身旋转状态如何,子物体射灯需平滑旋转对准玩家。
当前代码实现
变量声明
public Transform target; public float chaseSpeed = 5f; public float chaseRotationSpeed = 5f; public float followDistance = 2f; private Transform spotlight;
Start方法
void Start() { // 缓存射灯引用 spotlight = GameObject.Find("Spot Light").transform; }
Update方法
void Update() { if (isChasing) { ChasePlayer(); } }
ChasePlayer方法
void ChasePlayer() { autoMove = false; // 计算与玩家保持固定距离的目标位置 Vector3 targetPosition = player.position - (player.position - transform.position).normalized * followDistance; transform.position = Vector3.MoveTowards(transform.position, targetPosition, chaseSpeed * Time.deltaTime); // 平滑旋转射灯看向玩家 Vector3 lightDirection = player.position - transform.position; Quaternion lightRotation = Quaternion.LookRotation(lightDirection); if (spotlight != null) { spotlight.rotation = Quaternion.Slerp(spotlight.rotation, lightRotation, Time.deltaTime * chaseRotationSpeed); } }
现存问题
- 将
chaseRotationSpeed设为100时,无人机位置异常,直接贴到玩家身上(该参数应仅控制射灯旋转,不影响无人机位置) - 不调整该参数时,射灯完全不旋转(始终保持(0,0,0)旋转值),且无人机无法从后方跟随玩家,反而处于玩家前方,仅随玩家移动但不对准玩家
脚本挂载在Main (Cone)对象上,附带无人机层级结构与设置截图、无人机与玩家位置关系截图。
问题分析与修复方案
1. 核心变量名错误(最关键)
你声明的变量是public Transform target;,但在ChasePlayer方法里全程用的是player——如果player没有额外定义,这会导致编译错误;如果是笔误,直接导致所有位置、旋转计算使用了未正确初始化的对象,这是所有问题的根源。必须统一变量名:
- 要么把变量声明改为
public Transform player; - 要么把方法里的所有
player替换为target
2. 无人机位置计算逻辑错误
当前的位置计算是基于无人机与玩家的当前相对方向来偏移,这会导致无人机跑到玩家前方。正确的“后方”应该基于玩家的朝向来计算:
// 计算玩家后方的目标位置:玩家位置减去自身朝向正方向 × 跟随距离 Vector3 targetPosition = player.position - player.forward * followDistance; transform.position = Vector3.MoveTowards(transform.position, targetPosition, chaseSpeed * Time.deltaTime);
如果玩家的朝向是基于相机视角,可以改用Camera.main.transform.forward来定义“后方”,确保无人机始终在玩家视角的后方区域。
3. 射灯旋转无效的修复
- 可靠获取射灯引用:如果射灯是
Main (Cone)的子物体,用transform.Find("Spot Light")替代GameObject.Find,避免场景中重名对象干扰:void Start() { spotlight = transform.Find("Spot Light"); } - 修正旋转方向计算:应该用射灯自身的位置指向玩家,而不是无人机本体的位置,避免射灯与本体有偏移时方向错误:
Vector3 lightDirection = player.position - spotlight.position; Quaternion targetLightRotation = Quaternion.LookRotation(lightDirection); - 确保参数隔离:检查代码中是否有其他逻辑误用了
chaseRotationSpeed,当前给出的位置计算代码并没有用到该参数,大概率是变量名错误导致的连锁问题,修复变量名后即可解决参数影响位置的问题。
修复后的完整ChasePlayer示例
void ChasePlayer() { autoMove = false; // 修复:基于玩家朝向计算后方位置 Vector3 targetPosition = player.position - player.forward * followDistance; transform.position = Vector3.MoveTowards(transform.position, targetPosition, chaseSpeed * Time.deltaTime); if (spotlight == null) return; // 修复:用射灯自身位置计算指向玩家的方向 Vector3 lightDirection = player.position - spotlight.position; // 可选:如果不需要垂直旋转,锁定Y轴高度,避免射灯上下摆动 // lightDirection.y = spotlight.position.y; Quaternion targetLightRotation = Quaternion.LookRotation(lightDirection); // 平滑旋转射灯 spotlight.rotation = Quaternion.Slerp(spotlight.rotation, targetLightRotation, Time.deltaTime * chaseRotationSpeed); }
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

