C# 即使在旋转约束冻结的情况下也会出现奇怪的对象旋转(Unity引擎)

C# 即使在旋转约束冻结的情况下也会出现奇怪的对象旋转(Unity引擎),c#,unity3d,rotation,game-physics,C#,Unity3d,Rotation,Game Physics,我有一个3D世界空间的游戏。游戏是2D的。因此,玩家的位置冻结在1轴上,旋转冻结在2轴上。位置冻结工作正常。然而,有些玩家在游戏过程中遇到了不想要的对象旋转,即使是在冻结的约束条件下(我在测试期间从未遇到过这样的问题) 我自己测试时的约束: 我的代码(玩家移动脚本) 公共阶级运动:单一行为 { 公共刚体; 公共力=500; 专用平面=新平面(Vector3.up,Vector3.zero); 公众浮标速度; 公共浴池; 私有void Start() { 刚体rb=GetComponent()

我有一个3D世界空间的游戏。游戏是2D的。因此,玩家的位置冻结在1轴上,旋转冻结在2轴上。位置冻结工作正常。然而,有些玩家在游戏过程中遇到了不想要的对象旋转,即使是在冻结的约束条件下(我在测试期间从未遇到过这样的问题)

我自己测试时的约束:

我的代码(玩家移动脚本)

公共阶级运动:单一行为
{
公共刚体;
公共力=500;
专用平面=新平面(Vector3.up,Vector3.zero);
公众浮标速度;
公共浴池;
私有void Start()
{
刚体rb=GetComponent();
rb.centerOfMass=矢量3.0;
rb.惯性旋转=四元数.恒等式;
}
void FixedUpdate()
{
Cursor.visible=false;
Cursor.lockState=CursorLockMode.constrated;
if(输入。GetMouseButton(0))
{
如果(阻力值>0.25)
{
var-ray=Camera.main.screenpointoray(Input.mousePosition);
浮动进入;
if(平面光线投射(光线,向外输入))
{
var hitPoint=ray.GetPoint(输入);
var mouseDir=hitPoint-gameObject.transform.position;
mouseDir=mouseDir.normalized;
rb.AddForce(mouseDir*clickForce);
}
Plane playerPlane=新平面(向量3.up,变换.position);
Ray rayy=Camera.main.ScreenPointRoay(输入.鼠标位置);
浮动hitdist=0.0f;
if(playerPlane.Raycast(rayy,out hitdist))
{
Vector3 targetPoint=rayy.GetPoint(hitdist);
四元数targetRotation=Quaternion.LookRotation(targetPoint-transform.position);
transform.rotation=Quaternion.Slerp(transform.rotation,targetRotation,speed*Time.deltaTime);
}
}
}
}
}

提前谢谢

如@Iggy所示,指定给变换将忽略并覆盖刚体约束。要解决此问题,可以使用一些向量数学和
四元数.LookRotation
的第二个参数来限制局部向上轴位于其当前方向。评论中的解释:

if (playerPlane.Raycast(rayy, out hitdist))
{
    Vector3 targetPoint = rayy.GetPoint(hitdist);
    Vector3 targetDir = targetPoint - transform.position;
    // Find direction orthogonal to both targetDir and current local up.
    // this will become local right.
    Vector3 newLocalRight = Vector3.Cross(transform.up, targetDir);
    
    // If local up and target dir are colinear, do something sensible
    // like not changing the rotation
    if (newLocalRight == Vector3.zero) 
    { 
        /* something sensible */
        /* doing nothing may be the sensible choice */ 
    }
    else 
    {
        // If they are not colinear, determine the direction perpendicular to local up 
        // and local right. This will be the fixed forward direction.
        Vector3 newLocalForward = Vector3.Cross(newLocalRight, transform.up);

        // Assign a rotation using the fixed forward direction, and the current local up
        Quaternion targetRotation = Quaternion.LookRotation(newLocalForward, 
                transform.up);
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 
                speed * Time.deltaTime);
    }
 
}

主刚体中还有其他刚体吗?对象是否靠近场景的原点?当你移动到很远的地方时,事情会变得很奇怪。该对象由6个带有网格碰撞器(没有刚体)的子对象组成。一名玩家在距离场景原点20分的距离内遇到了这个问题,另一名玩家在210-220的距离内遇到了这个问题。你确定碰撞没有问题吗?如果没有它们,它会工作吗?这个小故障很难发现,但是,子对象之间有一些网格碰撞器(相交)。也许,这会引起一个问题?看起来你把物理力和直接变换混合在一起了。刚体约束在这种情况下没有效果。这是明智之举。测试10分钟后,没有出现故障。我会进一步测试,不过还是要谢谢你!
if (playerPlane.Raycast(rayy, out hitdist))
{
    Vector3 targetPoint = rayy.GetPoint(hitdist);
    Vector3 targetDir = targetPoint - transform.position;
    // Find direction orthogonal to both targetDir and current local up.
    // this will become local right.
    Vector3 newLocalRight = Vector3.Cross(transform.up, targetDir);
    
    // If local up and target dir are colinear, do something sensible
    // like not changing the rotation
    if (newLocalRight == Vector3.zero) 
    { 
        /* something sensible */
        /* doing nothing may be the sensible choice */ 
    }
    else 
    {
        // If they are not colinear, determine the direction perpendicular to local up 
        // and local right. This will be the fixed forward direction.
        Vector3 newLocalForward = Vector3.Cross(newLocalRight, transform.up);

        // Assign a rotation using the fixed forward direction, and the current local up
        Quaternion targetRotation = Quaternion.LookRotation(newLocalForward, 
                transform.up);
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 
                speed * Time.deltaTime);
    }
 
}