Planet Trajectory Prediction

I am trying to create a script to predict the trajectory of objects the player shoots. The physics system is a planet like gravity thing, where every fixedupdate a force is applied from a script on a nonmoving planet to all affectable objects that the player can shoot. The player shooting script takes in an input of a starting force multiplier and a direction. How can I predict the trajectory the players bullets will be shot in?

If it helps, here is how gravity is applied to each “bullet”.

void AttractObject(Attracted toAttract, float Multiplier)
    {
        Rigidbody2D toAttractRb = toAttract.GetComponent<Rigidbody2D>();

        Vector3 direction = rb.position - toAttractRb.position;
        float distance = direction.magnitude;

        float forceMultiplied = (rb.mass * toAttractRb.mass) / Mathf.Pow(distance, 2);
        Vector3 force = direction.normalized * forceMultiplied * 30;

        toAttractRb.AddForce(force * Multiplier);
    }

This is called once every fixedupdate run.

After some testing and a lot of experimenting, I managed to create some sort of trajectory prediction. However, its always a little off and this can end in there being a large difference. (It’s also probably terribly optimized).

// Gets all the points the orbit path will take
    public static Vector2[] GetPoints(Rigidbody2D rb, Vector2 velocity, int steps)
    {
        //The size of the returned array
        Vector2[] results = new Vector2[steps];

        //Findsall objects that gravity will affect
        Attractor[] planetsA = Object.FindObjectsOfType<Attractor>();
        //Creates a new simulate body to not adjust the positions of the real bodies, with a starting position multiplied by a random number gotten from testing
        SimulateBody s = new SimulateBody(rb, velocity * 0.138f);

        //Simulates movement and velocity.
        for (int i = 0; i < steps; ++i)
        {
            //Reverses attraction and applies the gravity force to the velocity
            for (int y = 0; y < planetsA.Length; y++)
            {
                s.Velocity += ReverseAttraction(rb, planetsA[y], s.position) * 0.02f;
            }
            //Adds the velocity to the position of the object
            s.position += s.Velocity;
            //Sets the location in the array position
            results[i] = s.position;
        }
        return results;
    }

    //Reverses the attraction formula between 2 objects.
    private static Vector2 ReverseAttraction(Rigidbody2D rb, Attractor a, Vector2 pos)
    {
        Vector3 direction = (Vector2)a.transform.position - pos;
        float distance = direction.magnitude;

        float forceMultiplied = (a.FinalMass * rb.mass) / Mathf.Pow(distance, 2);
        Vector3 force = direction.normalized * forceMultiplied * 30;
        return force;
    }

    //A simulated body
    class SimulateBody
    {
        public Vector2 Velocity;
        public Vector2 position;

        public SimulateBody (Rigidbody2D rb, Vector2 StartVelocity)
        {
            position = rb.position;
            Velocity = StartVelocity;
        }
    }

Bump

this is standard trajectory equation
s = vt + (gt*t)/2

s - final position from origin (Vector3)
v - initial velocity (Vector3)
g - gravitation vector (Vector3)
t - time of flight (float)

if your g changes with position this is going to be quite difficult to do analytically. It’s probably going to be a differential equation.

Erm… yeah, its going to be a differential equation (if I got the vocabulary right, and what I tried to do is above), as there are multiple sources of gravity and the strength of the gravitational pull is going to change…

As I see it you got 3 options:

  1. Use multiscene physics. (copy all objects into new physics scene and simulate behavior there)
  2. Discretization - do calculation with some discrete step of time. (but as you know it is not going to be precise).
  3. Discretization with simulation correction. You can correct the movement of the body with what was calculated with discrete simulation. Not 100% physically correct but more predictable.

If your world is not super complicated option 1. is probably the best.

I’ll do number one then, it sounds like a good idea, as my world isn’t too complicated.

On second thought, I don’t know if I can do that, as it needs to constantly update on runtime as the direction the player shoots in is constantly changing, and I’m, not sure how that can be simulated .

Copy every frame and manually simulate by calling simulate.
You can do manual simulation in unity3d.

Oh, I didn’t know about that, but I still have a question. How can I copy all of my objects onto a new scene and instantiate them there? I could probably copy all of my objects, but how would one go about generating two scenes at once? A quick google search didn’t seem to get me many results.

Start here