Basic Trajectory Prediction in Unity
By: Dan Schatzeder
Tags: Game Development, Software Development, Unity, Gamedevhq, Physics

Over the weekend, Austin Mackrell and I wanted to try out implementing the prediction and visualization of a trajectory in 2-D before it fires. Simply put, we’re firing an object through a gravity affected scene with a certain force, and we want to predict and show the path it would take before we fire it. We saw a ton of articles about it and have seen a number of games implement it in some way. There seemed to be two popular ways to do it, each having its own strengths and weaknesses.

Basic intention of Trajectory Prediction

Option One is to manually calculate how each of the Physics variables, like Force, Mass, Velocity, and Gravity would affect the object. With all the proper information and formulas, one can accurately forecast this.

Option Two is to create a parallel scene in which physics are drastically accelerated. Every time you show intent to launch the object in your main scene, you’re essentially launching the object in an duplicated scene, which is completing the action at an almost instantaneous speed. Main Scene passes launch information into Duplicate Scene, and Duplicate Scene passes the results of that launch back to Main Scene.

I chose Option One because I like how Math can in theory, perfectly calculate things for us in front of our eyes. Austin chose Option Two, and we thought it’d be interesting to illustrate and contrast the two.

It sounded easy.

Most people will know Trajectory Projection from Angry Birds

It sounded easy until I attempted it. The bad news: there aren’t any mainstream methods of predicting this for us within Unity, we’ll have to build it ourselves. The good news: Many have been here before us. Before video games, before computer simulation and before coding, we’ve had science. Mathematicians and physicists have been at this since long before us. As early as four hundred years ago, Galileo was demonstrating accurate Parabolic Trajectory.

f(t) = (x0 + x*t, y0 + y*t - g*t²/2)

This is our mother equation.

Looks complicated, I know. Let’s start basic. Take an object moving at a fixed directional speed through a two dimensional space, not being affected by gravity. I fire a bullet upwards at a speed (velocity) of 1x and 2y per second.

The multitude of terms here can get dizzying quick. One helpful thing to note is the synonymity of Vector Velocity and Direction. Our object is traveling 1x and 2y every second, and both of these can be stored in one variable, a Vector2. Therefore, our Vector Velocity is (1ₓ, 2ᵧ) per time unit. Our Direction is also a Vector2 of the same ratio as V.V. The useful distinction is that we’ll normalize the ratio for Direction, which simplifies it into a magnitude of 1. What this boils down to is: Our V.V. is (1ₓ, 2ᵧ), normalized via Unity, returns ~(0.45ₓ, 0.89ᵧ), our Direction. Direction will be particularly useful later when we’re applying Force to our object. Notice they retain the same ratio; Y is twice as much as X. This is a feature in Unity that is inherently used often, even though you may not notice. Ever use transform.up, left, right, down, forward, or back? They’re constantly referenced in Unity, because the information they hold is very useful.

Serialization of transform.up for this object. Do it some time and see for yourself. Transform Directions are always returned to us in magnitudes of 1, meaning the maximum value for X and Y are 1, when the other is 0. The same applies for all transform.directions, AKA the red, blue, and green axes of any object.

TANGENT TIME: Ever wonder why the most optimum angle for launching objects is 45°? Probably not, but I’ll tell you anyway. Notice at the end of the GIF where I set the Rotation to -45°. Transform.Up has X and Y equal at about 0.707 each. Add these together for a sum of ~1.41. No other possible sum of X and Y normalized is greater than 1.41. It’s the best angle for applying force to, because both axes are receiving the highest possible force. If you feel like 1.41 sounds familiar, it’s the square root of two. It’s the length of a hypoteneuse whose Triangle has minor sides equal to 1, with minor angles of, you guessed it, 45°. No coincidence that it’s a significant number here.

Going off of this, we can predict where the object will be by just asking how much Time has passed. I want the position of X after 5 seconds, so I’ll take the Origin of X and add the xVelocity * 5. Do the same to Y.

x(t) = x0 + x*t

y(t) = y0 + y*t

Combine into one Vector2 — f(t) = (x0 + x*t, y0 + y*t)

So at any given point in time, add the Velocity * Time to the Origin.

The green line represents all positions at a Velocity of 1x, 2y. Converted to slope formula, which is represented in terms of Y, it’s y=2x (b is 0), or Y is traveling twice as fast as X.

Follow the green line. Every second, we’re traveling 1x and 2y. At 2 seconds, we’re at 2x and 4y. At 5, we’re at 5x, 10y.

We can predict every point of this trajectory at any point in time. There are infinite points.