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:
- Use multiscene physics. (copy all objects into new physics scene and simulate behavior there)
- Discretization - do calculation with some discrete step of time. (but as you know it is not going to be precise).
- 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