我正在为 Unity 开发一款适用于 Android 的无尽跑步游戏。我不想使用运动学刚体。因此涉及物理,但刚体应该默认沿着预定义的路径运行。(并通过用户操作跳跃或改变车道)。直线移动很容易。我已经做到了,但我希望在游戏的下一个阶段有回合。它似乎有效,但有时会变得紧张,并且转弯不像我想要的那样平滑。如果我提高速度,玩家就会变得不稳定。无论速度如何,您能否帮我优化代码以获得更顺畅的转弯。
据我搜索,我在互联网上找不到答案,可能人们更频繁地使用运动学刚体,而不是处理物理问题。所以我使用.AddForce
and .AddTorque
。我现在使用带有预定义转弯(路段)的预制件。所以它是随着玩家移动而产生的。每个道路预制件都有一条用于移动路径的样条曲线(我想是基于 Unity 2015 程序样条曲线生成视频的免费资产)。所以玩家沿着样条线拾取一个节点并将其设置为目标并使用它的旋转转向使用 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);
}