2017-08-03 2 views
1

Nehmen wir an, Sie haben ein Rigidbody Objekt, das sich bewegt. Dieses Objekt wird über Rigidbody.AddForce oder Rigidbody.velocity Force hinzugefügt. Das Objekt kann einen anderen Gegenstand treffen und die Richtung ändern.Vorhersage der Position eines Rigidbody-Objekts in x-Sekunden

Ich weiß über Extrapolation aber in diesem Fall ist es fast unmöglich, eine Formel zu verwenden, um die Position des Objekts in x Sekunden zu erhalten, da das Objekt ein anderes Objekt treffen kann und die Geschwindigkeit/Richtung im Prozess ändern.

Einheit 2017 eingeführt Physics.autoSimulation und Physics.Simulate, um dieses Problem zu lösen. Für 2D-Physik ist das Physics2D.autoSimulation und Physics2D.Simulate. Alles, was ich getan habe, war zuerst Physics.autoSimulation zu false gesetzt dann rufen Sie die Physics.Simulate Funktion.


In meinem Beispiel ich, wo ein Rigidbody wäre in 4 Sekunden nach der Zugabe von Kraft auf sie, scheint es zu funktionieren gut für kleine Sekunden wie 1 wissen wollte. Das Problem ist, dass wenn ich größere Zahlen wie 5 und höher an die Simulate Funktion übergebe, ist die vorhergesagte Position nicht genau. Es ist weit weg.

Warum passiert das und wie kann ich es beheben? Dieses Problem ist auf Android-Geräten schlimmer.

Meine aktuelle Unity-Version ist Unity 2017.2.0b5.

Unten ist der Beispielcode, den ich verwende. Das guide GameObject wird einfach verwendet, um anzuzeigen, wo diese vorhergesagte Position ist.

public GameObject bulletPrefab; 
public float forceSpeed = 50; 

public GameObject guide; 

// Use this for initialization 
IEnumerator Start() 
{ 
    //Disable Physics AutoSimulation 
    Physics.autoSimulation = false; 

    //Wait for game to start in the editor before moving on(NOT NECESSARY) 
    yield return new WaitForSeconds(1); 

    //Instantiate Bullet 
    GameObject obj = Instantiate(bulletPrefab); 

    Rigidbody bulletRigidbody = obj.GetComponent<Rigidbody>(); 

    //Calcuate force speed. (Shoot towards the x + axis) 
    Vector3 tempForce = bulletRigidbody.transform.right; 
    tempForce.y += 0.4f; 
    Vector3 force = tempForce * forceSpeed; 

    //Addforce to the Bullet 
    bulletRigidbody.AddForce(force, ForceMode.Impulse); 

    //yield break; 
    //Predict where the Rigidbody will be in 4 seconds 
    Vector3 futurePos = predictRigidBodyPosInTime(bulletRigidbody, 4f);//1.3f 
    //Show us where that would be 
    guide.transform.position = futurePos; 
} 

Vector3 predictRigidBodyPosInTime(Rigidbody sourceRigidbody, float timeInSec) 
{ 
    //Get current Position 
    Vector3 defaultPos = sourceRigidbody.position; 

    Debug.Log("Predicting Future Pos from::: x " + defaultPos.x + " y:" 
     + defaultPos.y + " z:" + defaultPos.z); 

    //Simulate where it will be in x seconds 
    Physics.Simulate(timeInSec); 

    //Get future position 
    Vector3 futurePos = sourceRigidbody.position; 

    Debug.Log("DONE Predicting Future Pos::: x " + futurePos.x + " y:" 
     + futurePos.y + " z:" + futurePos.z); 

    //Re-enable Physics AutoSimulation and Reset position 
    Physics.autoSimulation = true; 
    sourceRigidbody.velocity = Vector3.zero; 
    sourceRigidbody.useGravity = false; 
    sourceRigidbody.position = defaultPos; 

    return futurePos; 
} 

Antwort

2

Sie sind sogar glücklich, dass der Wert von 1 bei-alle gearbeitet hat. Sie sollten nicht einen beliebigen Wert über 0.03 an die Physics.Simulate oder Physics2D.Simulate Funktion übergeben.

Wenn der Wert über 0.03 ist, müssen Sie es in Stücke, dann verwenden Sie die Simulate Funktion in einer Schleife. Dekrementieren der x Zeit bei der Überprüfung, ob es noch mehr oder gleich Time.fixedDeltaTime ist, sollte es tun.

ersetzen

Physics.Simulate(timeInSec); 

mit

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

Ihre neue komplette predictRigidBodyPosInTime Funktion wie folgt aussehen sollte:

Vector3 predictRigidBodyPosInTime(Rigidbody sourceRigidbody, float timeInSec) 
{ 
    //Get current Position 
    Vector3 defaultPos = sourceRigidbody.position; 

    Debug.Log("Predicting Future Pos from::: x " + defaultPos.x + " y:" 
     + defaultPos.y + " z:" + defaultPos.z); 

    //Simulate where it will be in x seconds 
    while (timeInSec >= Time.fixedDeltaTime) 
    { 
     timeInSec -= Time.fixedDeltaTime; 
     Physics.Simulate(Time.fixedDeltaTime); 
    } 

    //Get future position 
    Vector3 futurePos = sourceRigidbody.position; 

    Debug.Log("DONE Predicting Future Pos::: x " + futurePos.x + " y:" 
     + futurePos.y + " z:" + futurePos.z); 

    //Re-enable Physics AutoSimulation and Reset position 
    Physics.autoSimulation = true; 
    sourceRigidbody.velocity = Vector3.zero; 
    sourceRigidbody.useGravity = false; 
    sourceRigidbody.position = defaultPos; 

    return futurePos; 
} 
+0

Dank. Das hat gut funktioniert. – Programmer

Verwandte Themen