c# - 控制沿路径移动的非运动学刚体

标签 c# unity3d rigid-bodies

我正在使用 Unity 开发一款适用于 Android 的无尽跑酷游戏。我不想使用运动学刚体。所以涉及物理,但默认情况下,刚体应该沿着预定义的路径运行。 (并通过用户操作跳跃或改变车道)。直线移动很容易。我已经做到了,但我希望在游戏的下一阶段有轮流。它似乎有效,但有时会变得紧张,转弯不像我想要的那样顺畅。如果我提高速度,玩家就会变得不稳定。能否请您帮我优化一下代码,让无论速度如何都能更顺畅地转弯。

据我搜索,我无法在互联网上找到答案,可能人们更频繁地使用运动学刚体以避免处理物理问题。所以我使用 .AddForce.AddTorque。我现在使用带有预定义转弯(路段)的预制件。所以它是在玩家移动时产生的。每个道路预制件都有一个用于移动路径的样条曲线(我想是基于 Unity 2015 程序样条曲线生成视频的免费 Assets )。所以玩家沿着样条曲线拾取一个节点并将其设置为目标并使用其旋转转向使用 AddTorque。

如果我切换到运动学刚体,也许会更容易。也许这是理想的,但我坚持这样做是为了学习物理,有些人可能会发现它对另一个项目有用,因为这方面没有足够的资源。

void FixedUpdate()
  {


    if (!jump)
    {
        //maxangle = Mathf.Clamp(r.velocity.magnitude * 2f,3,15f);
        maxangle = r.velocity.magnitude;

        r.constraints = RigidbodyConstraints.None;
        r.constraints = RigidbodyConstraints.FreezeRotationZ | RigidbodyConstraints.FreezeRotationX;
        TurnToTarget(transform, sample.Rotation,target, maxangle);
        r.constraints = RigidbodyConstraints.None;
        r.constraints = RigidbodyConstraints.FreezeRotationZ | RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY;
    }
    //Debug.Log(currentroad.transform.name + maxangle);

    if (!GameManager.gameManager.dead  && running)
    {
        r.isKinematic = false;
        //Debug.Log(transform.position.y);
        var speed = r.velocity.magnitude;
        Vector3 directionOfTarget = (target - transform.position).normalized;

        if (speed < runspeed)
        {
            //r.velocity += Vector3.forward * 1f;
            Debug.Log(r.velocity.z+ " " + r.velocity.magnitude);
            Debug.Log(directionOfTarget);
            r.AddForce(directionOfTarget* (runspeed-speed), ForceMode.VelocityChange);
        }
        if (transform.position.y > 2.7f)
        {
            r.mass = 50000f;
            Physics.gravity = new Vector3(0, -100f, 0);
        }
        if (grounded)
        {
            r.mass = 10f;
            Physics.gravity = new Vector3(0, -10f, 0);
        }

private void TurnToTarget(Transform transform, Quaternion targetrot, Vector3 movePoint, float maxTurnAccel)
 {
      Vector3 directionOfTarget = (movePoint -transform.position).normalized;
      Vector3 directionInEulers = targetrot.eulerAngles;

      Vector3 offsetInEulers = ClampHeading(directionInEulers) - ClampHeading(transform.eulerAngles);
    offsetInEulers = ClampHeading(offsetInEulers);
    //optional

    Vector3 angularVelocity = r.angularVelocity / Time.fixedDeltaTime;
    if (offsetInEulers.sqrMagnitude < Mathf.Pow(maxTurnAccel, 2))
    {
        if (offsetInEulers.y < 0)
        {
            if (angularVelocity.y < offsetInEulers.y)
            {
                offsetInEulers.y = -offsetInEulers.y;
            }
        }
        else
        {
            if (angularVelocity.y > offsetInEulers.y)
            {
                offsetInEulers.y = -offsetInEulers.y;
            }
        }
        if (offsetInEulers.x > 0)
        {
            if (angularVelocity.x < -offsetInEulers.x)
            {
                offsetInEulers.x = -offsetInEulers.x * 2;
            }
        }
        else
        {
            if (angularVelocity.x > -offsetInEulers.x)
            {
                offsetInEulers.x = -offsetInEulers.x * 2;
            }
        }
        if (offsetInEulers.z > 0)
        {
            if (angularVelocity.z < -offsetInEulers.z)
                offsetInEulers.z = -offsetInEulers.z * 2;
        }
        else
        {
            if (angularVelocity.z > -offsetInEulers.z)
                offsetInEulers.z = -offsetInEulers.z * 2;
        }
    }
    offsetInEulers = ClampVector(offsetInEulers, -maxTurnAccel, maxTurnAccel);
    //Debug.Log(currentroad + " " + offsetInEulers + " " + r.angularVelocity + " " + directionOfTarget + " " + ClampHeading(directionInEulers)+" " +transform.eulerAngles);

    r.AddRelativeTorque(transform.up * offsetInEulers.y);
    //r.AddTorque(offsetInEulers*r.velocity.magnitude);

}

最佳答案

您可以查看样条曲线。您可以减少沿着路径移动角色的计算量,方法是计算在角色从一个点移动到另一个点时需要沿着该路径移动多少点才能使移动看起来平滑。

当角色快速移动时,有时会使用模糊效果来减少需要绘制的多边形数量。

关于c# - 控制沿路径移动的非运动学刚体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57546513/

相关文章:

c# - 如何将 id 数字字符串传递给此类

linux - 查看Qt中用户使用的是哪个桌面环境(Linux)

c# - 刚体移动时,有时刚体速度为零

java - 我的刚体碰撞代码如何不一致?

c# - 字符串转换为日期时间

c# - 正确转换为枚举

c# - 如何在 C# 中将 LPCWSTR 编码为字符串?

c# - 用于在 Unity3D 中定位 3D 对象的 OpenCV 旋转(Rodrigues)和平移向量

c# - 如何在 Windows 中获取和设置系统音量

math - 如何计算多面体的质量和惯性矩?