物理。模拟每一帧

时间:2019-07-17 12:20:50

标签: c# unity3d

我有一个游戏对象,当玩家选择力和方向时,将使用physics.simulate绘制运动轨迹和终点位置的线。如果我每0.5f秒使用一次,则效果很好,但我必须预测每帧的轨迹和结束位置,但是游戏却落后了。如何预测每帧的轨迹和结束位置?

private IEnumerator destcor()
{
    while (true)
    {
        yield return new WaitForSeconds(0.3f);
        touchhandler.listofcoll.Clear();
        touchhandler.force = (float)Math.Pow(distanceToRoller, 3);

        touchhandler.RollerMove();
        endpos = touchhandler.CheckPosition(rollerobj.GetComponent<Rigidbody>());
        destination.transform.position = endpos;
    }
}

public Vector3 CheckPosition(Rigidbody defaultRb)
{
    Physics.autoSimulation = false;
    defaultRb = GetComponent<Rigidbody>();
    Vector3 defaultPos = defaultRb.position;
    Quaternion defaultRot = defaultRb.rotation;

    float timeInSec = timeCheck;

    while (timeInSec >= Time.fixedDeltaTime)
    {
       timeInSec -= Time.fixedDeltaTime;
       Physics.Simulate(Time.fixedDeltaTime);
    }//end while

    Vector3 futurePos = defaultRb.position;

    Physics.autoSimulation = true;

    defaultRb.velocity = Vector3.zero;
    defaultRb.angularVelocity = Vector3.zero;

    defaultRb.transform.position = defaultPos;
    defaultRb.transform.rotation = defaultRot;

    return futurePos;
}

1 个答案:

答案 0 :(得分:1)

通常,您应该在FixedUpdate中进行与Physics引擎(也包括RigidBody)相关的所有操作,或者因为您正在使用yield return new WaitForFixedUpdate();使用IEnumerator- 不是,每一帧。

有一个很好的理由说明为什么不是以每帧为基础而是以固定的时间间隔(因此称为“ FixedUpdate”)来进行物理更新:通常比较耗时且占用大量资源。因此,为避免巨大的滞后,您应该避免每帧都使用物理。

让您失望的另一件事是反复进行GetComponent通话。您应该只做一次,以后再使用该引用:

private RigidBody rigidBody;

private void Awake()
{
    rigidBody = rollerobj.GetComponent<Rigidbody>();
}

private IEnumerator destcor()
{
    while (true)
    {
        yield return new WaitForFixedUpate();

        touchhandler.listofcoll.Clear();
        touchhandler.force = (float)Math.Pow(distanceToRoller, 3);

        touchhandler.RollerMove();
        endpos = touchhandler.CheckPosition(rigidBody);
        destination.transform.position = endpos;
    }
}

CheckPosition这一行中

defaultRb = GetComponent<Rigidbody>();

毫无道理!您是否已经传递了有效的RigidBody参考。因此,在此处覆盖它似乎有点适得其反。

如果您想在此处再次使用某种备用,则可以将引用存储在Awake中一次,然后像例如

那样重新使用它。
private RigidBody rigidBody;

private void Awake()
{
     rigidBody = rollerobj.GetComponent<Rigidbody>();

     // now add the fallback here already
     if(!rigidBody) rigidBody = GetComponent<RigidBody>();
     // or maybe you could even use
     //if(!rigidBody) rigidBody = GetComponentInChildren<RigidBody>(true);
     // in order to buble down the entire hierachy until a RigidBody is found
}