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

Unity2D基于子对象计算父物体旋转时出现异常抖动问题咨询

Unity物体旋转逻辑异常抖动问题排查

问题复现场景

  • 场景内共3个对象:RotatePoint(黑色圆形,根父对象)、Square(红色矩形,子对象)、Circle(白色圆形,子对象),三者组成层级组合,RotatePoint为旋转中心
    场景示意图
  • 预期实现效果:以RotatePoint为中心,整个对象组合跟随鼠标位置平滑旋转
  • 初始挂载在RotatePoint上的实现脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestRotate : MonoBehaviour
{
    //旋转中心对象
    public Transform rotatePoint;
    //白色圆形子对象
    public Transform circle;

    void Update()
    {
        Vector3 MouseWorldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Debug.LogWarning("circle.pos" + circle.position);
        Vector3 direction = MouseWorldPoint - circle.position;

        float radians = Mathf.Atan2(direction.y, direction.x);
        float degrees = radians * Mathf.Rad2Deg;
    
        rotatePoint.eulerAngles = new Vector3(0,0,degrees);
        Debug.DrawLine(circle.position,MouseWorldPoint,Color.red);
    }
}

异常表现

  • 鼠标距离Circle子对象较远时,旋转效果符合预期,整个组合以RotatePoint为中心跟随鼠标平滑旋转
    正常旋转效果
  • 鼠标移动到距离Circle子对象一定阈值范围内时,整个组合开始弹跳抖动,距离越近越容易出现无规律360度旋转的问题
    异常旋转效果

临时修复方案

将方向计算的参考坐标从子对象Circle的位置替换为父对象RotatePoint自身位置后,所有距离下的旋转效果均恢复正常,修改后代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestRotate : MonoBehaviour
{
    //旋转中心对象
    public Transform rotatePoint;
    //白色圆形子对象
    public Transform circle;

    void Update()
    {
        Vector3 MouseWorldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        //将参考点从circle.position修改为rotatePoint.position
        Vector3 direction = MouseWorldPoint - rotatePoint.position;
        Debug.LogWarning("circle.pos" + circle.position);

        float radians = Mathf.Atan2(direction.y, direction.x);
        float degrees = radians * Mathf.Rad2Deg;
    
        rotatePoint.eulerAngles = new Vector3(0,0,degrees);
        Debug.DrawLine(circle.position,MouseWorldPoint,Color.red);
    }
}

修改后正常效果


问题成因说明

该问题不属于Unity引擎Bug,是典型的闭环反馈逻辑错误,触发逻辑如下:

  1. 初始代码形成了自反馈循环:用会随父对象旋转改变世界坐标的子对象位置作为角度计算参考点,计算出的角度又反过来赋值给父对象修改旋转状态,父对象旋转会立刻改变子对象的世界坐标,形成因果闭环。
  2. 鼠标距离Circle较远时,单帧旋转带来的Circle位置偏移量,相对于鼠标到Circle的总距离占比极小,计算出的角度误差可以忽略,因此看起来运行正常。
  3. 鼠标距离Circle极近时,单帧旋转带来的Circle位置偏移量占总距离的比例会被急剧放大:当前帧算出角度A赋值给父对象,父对象旋转后Circle立刻移动到新位置,此时鼠标相对于新位置的方向直接跳到角度B,下一帧又按角度B旋转,Circle再次位移,方向又跳到角度C,最终表现为无规律抖动、疯狂旋转。
  4. 参考点替换为RotatePoint后问题消失,是因为RotatePoint作为旋转中心,旋转时自身世界坐标不会发生任何变化,计算参考点固定,不会触发反馈循环,因此旋转始终稳定。

额外注意:2D场景下使用Camera.main.ScreenToWorldPoint转换鼠标坐标时,需要给鼠标屏幕坐标设置正确的Z值(即正交相机到2D平面的距离),否则坐标转换结果也会出现偏差。


内容的提问来源于stack exchange,提问作者li ming

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:54:19