Question about orbital mechanics in unity

Hi, I have trouble understanding part of code I got from another forum post about orbiting physics, and CodeMonkeys orbiting simulator tutorial.

I can’t figure out why I get same result with two different formulas. I’m also using Orbiting debugger from codemonkey so I can see what orbit I should be get if everything is done correctly.

Here is my code:

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();

        planetMass = rb.mass;

        if (useInitialVelocity)
        rb.velocity = initialVelocityDirection * initialVelocityAmount;

        velocity = rb.velocity;

        foreach(GravityTest planet in FindObjectsOfType<GravityTest>())
        {
            planets.Add(planet.GetComponent<Rigidbody2D>());
        }
    }

    public void GravityWithVelocity()
    {
        Vector3 acceleration = Vector3.zero;
        foreach (Rigidbody2D star in planets)
        {
            if (star.position != rb.position)
            {
                Vector3 forceDir = (star.position - rb.position).normalized;
                float sqrDst = (star.position - rb.position).sqrMagnitude;
                acceleration += forceDir * .001f * star.mass / sqrDst;
            }
        }

        velocity += acceleration;
        rb.velocity = velocity * Time.fixedDeltaTime;
    }

    private void GravityWithForce()
    {
        foreach(Rigidbody2D star in planets)
        {
            if(star.position != rb.position)
            {
                float r = Vector3.Distance(star.position, rb.position);
                float totalForce = -(.001f * star.mass * rb.mass) / (r * r);
                Vector3 force = (rb.position - star.position).normalized * totalForce;
                rb.AddForce(force);
            }
        }
    }

So the question is why is formula in GravityWithVelocity missing mass of the planet that is orbiting the star and producing same result as GravityWithForce?

Edit: So as soon as I posted I figured out that the formula is different for calculating velocity vs force. My first tought was that I have issue with code from tutorial that I attempted to simplify for my purposes. I still don’t really understand physics behind it, but all that matters is that code is correct!

The gravitational force that acts between two masses m_R and m, where m_R is the mass of the rigid body under observation, is given by F_G = -Gm_Rm/r^2, where r is the distance between the two masses and G is the gravitational constant. Your GravityWithForce() method pretty much uses this formula and calculates the total contributions of the gravitational force of each mass with respect to the rigid body and applies this force to it.

GravityWithVelocity() computes the acceleration due to the force using simple Newton’s 2nd Law (F = ma). Dividing both sides by m_R, since you want to find its acceleration, this gives a = -G*m/r^2. Acceleration is the derivative of velocity, so you find the net acceleration (line 27) then use an ODE solver to find velocity. It looks like you’re using Forward Euler but the actual formula is: f(x_t) = f(x_t-1) + h*f’(x), where x_t is the state at the current timestep, x_t-1 is the state in the previous timestep, and h is the time step (appropriately Time.fixedDeltaTime as you did). At t = 0, you need to place an initial condition, so your code should be something like:

void Start() {
     // everything else
     rb.velocity = 0;    // initial condition
}

void GravityWithVelocity() {
   // lines 20-31
   rb.velocity = rb.velocity + acceleration*Time.fixedDeltaTime;
  // or rb.velocity += acceleration*Time.fixedDeltaTime;
}

I think relying on GravityWithForce() is better in the long run, as implementing differential equations of dynamical systems is not worth the hassle when you could just understand what the equations are saying and apply all the forces to achieve the same result. Assigning rb.velocity is not recommended, people in the forums will tell you this and I learnt the hard way trying to implement a massive state space model in Unity.

2 Likes

This is exactly the kind of explanation I was looking for, thank you. As you said adding force seems to be a lot easier to understand, and changing velocity seems like additional step to get same result.

Just to state for the record here, it’s not so much as not being recommended, it’s that just like anything in code, if you directly write over a field, property (etc) you’re replacing what information was there before.

In the case of the velocity of a Rigidbody, you’re replacing its current velocity with one of your own choosing therefore loosing the information it had which might be the forces being applied elsewhere via the scripts or from collisions or the effects of gravity etc.

1 Like