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.