1
\$\begingroup\$

Okay, I have the following situation:

I want to launch a GameObject into orbit of a planet and using the dynamic rigidbody everything is working as I want. I simulate gravity and as it hits the surface again it bounces around nicely using the Box2D system.

However, I want to calculate the trajectory and visualise it on screen. I thought about it and came up with two solutions, but I run into some problems:

1 Simplectic integration for the trajectory

I simulate the trajectory using simplectic integration. However, as can be expected, the results are different for the dynamic rigidbody movement and the simplectic integration. This became very obvious when I launched two identical objects and simulated one dynamically and the other one simplectic. The code is as follows (all in FixedUpdate):

if (rb.isKinematic)
{
    velocity += forces / mass * Time.fixedDeltaTime;
    Vector2 newPosition = (Vector2)transform.position + velocity * Time.fixedDeltaTime;
    rb.MovePosition(newPosition);
}
else
{
    rb.AddForce(forces);
}

The simplectic / kinematic one is slower than the dynamic one. Weird.

2 Use Physics2D.simulate

According to https://docs.unity3d.com/ScriptReference/Physics2D.Simulate.html I can simulate it via code. However, this means that I have to set everything that is not to be simulated as disabled and simulate it for a given amount of time to calculate the trajectory. Not really what I was looking for, because I want to have a live trajectory update

3 Full simplectic That seems to be easy, but I want to have realistic collisions and bounces. Don't want to reinvent the wheel when Box2D should be sufficient.

4 Simplectic for simple movement, dynamic at collision This seems to be the logical candidate, but don't know if it is clever. Had no time to implement this yet, but should not be that difficult. Feels a bit icky...

So, question?

My questions are:

  • Can I reduce or eliminate the offset from solution 1?

  • If not, what whould be the most logical solution and / or am I missing one?

EDIT It was asked how I calculate the forces. This is simply Newton's law with squared distance:

public Vector2 CalculateForce(GameObject a, GameObject b) {
    // AUComponent is an interface type I have... not very special in itself.
    float mA = a.GetComponent<AUComponent>().Mass;
    float mB = b.GetComponent<AUComponent>().Mass;

    Vector2 r = b.transform.position - a.transform.position;
    return gravityConstant * mA * mB / r.sqrMagnitude * r.normalized;
}

However, the ever increasing offset is also happening with a constant force applied in a direction.

The masses of the AUComponent are equal to those of the RigidBody.

\$\endgroup\$
0
\$\begingroup\$

If you are dealing with a shorter period of time (even uo to 30 seconds, but sometimes even more), then you can simply use the Euler method. You just take the object, save it's position and start simulating it's behaviour by stepping through the desired time period in smaller steps.

Thisbis actually something like what unity's simulate does, but you don't have to disable anything.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ This is exactly what I am doing, but the positions don’t match up. The Unity dynamic integrator has a different result than the semi implicit euler that Box2D supposably uses. \$\endgroup\$ – avanwieringen Feb 27 '18 at 7:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.