You need to enable JavaScript to run this app. Unity自定义重力切换时玩家对象绕前向轴异常旋转问题求解
优惠活动
大模型
产品
解决方案
定价
更多

Unity自定义重力切换时玩家对象绕前向轴异常旋转问题求解

问题定位

你的代码存在3个核心错误,直接导致离开触发区时出现异常旋转:

1. 朝向更新逻辑的up轴硬编码为世界Y轴

Turning方法中调用transform.LookAt时,第二个参数固定传入了世界坐标下的Vector3(0, 1, 0)作为up参考轴,但你的重力方向是动态变化的,up轴应该和当前重力方向相反(也就是-down),当重力方向从(0,-1,0)切换到(1,0,0)时,你依然用世界Y轴当up参考,就会导致物体绕前向轴翻转。
修复代码:

transform.LookAt(transform.position + lookDirection, -this.down);

2. 离开触发区时速度旋转角度计算错误

你在OnTriggerStay里是计算originalDown到newDown的相对夹角来旋转速度,但到了OnTriggerExit里直接用了绝对角度newAngle(相对于(1,0,0)的角度)来旋转速度,相当于多转了几倍的角度,导致速度方向和朝向完全不匹配,附带异常旋转。
修复逻辑:和Stay逻辑一致,先获取退出前的原重力方向,再计算原重力到目标限值重力的相对角度来旋转速度。

3. 触发区退出时角度判断用了无符号角度

你原来用Vector3.Angle计算的是0-180度的无符号角度,当实际角度为负的时候会判断错误,无法正确匹配最近的限值,需要改成Vector3.SignedAngle。


完整修复后的OnTriggerExit代码

void OnTriggerExit()
{
    Vector3 originalDown = tControl.Down; // 先获取退出前的重力方向
    Vector3 exitDir = tTransform.position - gameObject.transform.position;
    // 改用带符号的角度计算,避免负角度判断错误
    float angle = Vector3.SignedAngle(exitDir, new Vector3(1, 0, 0), new Vector3(0, 0, 1));
    Vector3 newDown;
    float deltaAngle;
    
    if (Mathf.Abs(angle - MinLimit) < Mathf.Abs(angle - MaxLimit))
    {
        newDown = Quaternion.AngleAxis(MinLimit, new Vector3(0, 0, -1)) * new Vector3(1, 0, 0);
        deltaAngle = Vector3.SignedAngle(originalDown, newDown, new Vector3(0, 0, 1));
    }
    else
    {
        newDown = Quaternion.AngleAxis(MaxLimit, new Vector3(0, 0, -1)) * new Vector3(1, 0, 0);
        deltaAngle = Vector3.SignedAngle(originalDown, newDown, new Vector3(0, 0, 1));
    }

    Debug.Log("Exit: " + newDown + " " + deltaAngle);
    tControl.SetDirections(newDown);
    tRigidbody.velocity = Quaternion.AngleAxis(deltaAngle, new Vector3(0, 0, 1)) * tRigidbody.velocity;
}

额外校验项

确认玩家Rigidbody组件已经勾选Freeze Rotation Z,避免物理模拟额外产生绕Z轴的旋转。

内容的提问来源于stack exchange,提问作者Zoltán Király

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 13:48:03