Monster shadow


Trajectory Line in Unity (This ain't your mothers trajectory line)

Trajectory prediction lines are everywhere in puzzle games and you even see them in action games to simulate grenade throw arcs etc. This is a new method recently made possible with the addition of Multi-Scene Physics. We now have the ability to simulate frames into the future using the in-built physics system, taking into account the physics material of each object and even external forces like 2D force effectors... Making this significantly more powerful than your mothers trajectory line. Scripts and assets: ❤️ Become a Tarobro on Patreon: ========= 🔔 SUBSCRIBE: 🗨️ DISCORD: ✅ MORE TUTORIALS:

Game Maker's Toolkit
Hey! Cool tutorial but unfortunately it's not very performant. In your sample scene, enabling the trajectory line drops the framerate from - on my computer - a solid 60fps to about 26fps, and increases the render thread by 10 times (~0.8ms to ~9.7ms). I think the problem might be using Instantiate and Destroy on every frame. To anyone watching this and wanting to implement it, you might want to consider a slightly tweaked approach!
Maxx Golbraykh
Great video and concept! Much easier way of physics prediction than the mathy alternatives. It does come with some performance challenges, but nothing that (probably) can't be solved with a little work. Thanks for making this!!
@Game Maker's Toolkit I'll pin this thread so others can benefit from your discovery.
Game Maker's Toolkit
@Tarodev I've done a similar implementation in 2D, and instead of instantiating and destroying the ghost ball, I just set its position back to the cannon before doing the physics steps. Works nicely! Thanks again for the hard work put into the tutorial.
Yup, it certainly takes a toll. I've thought about it a little bit since this release and there are a few things to look into: *Reducing iterations. Increasing launch velocity can increase the length of the trajectory line, but may not be what you want *Object pooling (as you mentioned about the instantiation) *Reducing physics step time *Using a 'debounce' strategy where as the user is interacting only a fraction of iterations are calculated, lerping towards Max iterations as the player stops input. This is good because the first bounce is usually the most vital so they can line it up without lag and simply wait a second for the full line to be calculated. Not perfect.. Keen to hear other ideas
Might I ask how you had it define the field for you with whatever keybind you hit twice?
Why did you speed up this video?)
This was a DUMB editing mistake. I noticed after uploading it... It was only meant to speed up one section, so don't ask me how I managed it.
Jim Warden
the scripts and assets link is broken. plz fix it I can't download :(
I updated it with a direct github link
rennie moffat
Hi there I love this tutorial but when I tested under a more demanding project where I needed lots of plot points, my engine began to choke. How can I best manipulate plot spacing?
rennie moffat
Thanks so much!!! I was literally dreading having to create a Trajectory Prediction method today, until this!!! GENIUS!!
Just be aware, it can be quite expensive. Try to keep iterations as low as possible and you should be fine
Isn't this duplicate scene a memory hog? this scene is simple so it's cool, but what if i have an enormous terrain, or some complex colliders, some object with a gorillion tris, or whatever? is it viable?
It's not so much the double colliders, but the huge amount of physics steps being calculated every frame. You can perform trajectory calculations using simple math, but it doesn't take into account physics materials or effectors. It can also get complex if you want to simulate the bounces... So really it's a pros and cons kind of deal. But this technique is by no means performant. Cool though 😎
Bed Time Stories
That is very clever. I just wrote a script to calculate trajectory lines for a 2D game using circle casts and vector math. It works fantastically and I'm glad to have done it, but I think I'm going to switch to this method. Never thought of using scenes like this, especially for manually controlling physics steps. Thanks a ton :)
Bed Time Stories
@Tarodev Ah okay, was thinking about that. Appreciate the heads up.
Just a word of warning: your method will be insanely more performant. This method is calculating n physics frame every frame, so it can be very heavy. Download the package I provided, plop it into the scene and experiment before swapping over
Levi Ackerman
It's too high level for me. It's mind boggling how someone can come up with all of these solutions from the scratch I can barely follow the tutorial. I bet I wouldn't be able to come up a solution by my self from the scratch even after 20 years lol. I got spoiled by papa Brackeys simple tutorials so much
Don't say that brother. In 20 years you'll be making your own game engine ;)
Shiro Surfer
Oh very nice tutorial I can see myself using this and improving it as I go Btw that materials shaders so Cool do you have tutorial on those? Very pretty colors wow
Not yet, but I plan on making a video soon on my scene setups!
Ram Manohar
I'm blown away that u can create another scene inside a scene.. Never used them before
Roy [ Random Precision Software ]
Why do you make things complicated?..Why use create scene and put objects in.?
If you can show me a simpler way to handle a full physics simulation (including physics materials of each object), I'd love to see it! Always keen to learn.
Mr Slake
This is a Brackeys quality tutorial, thanks so much!
Well im stuck, it ok when it 1 cannon, if where more then 2 , it`s laging, i tested with 8 cannons that fires all at same time because it start physics.simulate() for each cannon > 300 simulations * fixedDeltaTimes * connonCount any ideas for optimise? tried to move simulation into waitAfterFixedUpdate noresults maybe there are some way to move simulate scene from main thread? Good idea with instantiate > object.reset I alreade addad object pooler for bullets
@Filoret ahhh, there are some which predict bounces as well (without physics materials though). That one is just the initial velocity
@Tarodev yep, sudenlly -)
Unfortunately I have not found a way to make it more performant other than re-using the physics object instead of destroy/instantiate every frame. I would assume 8 cannons would absolutely wreck any computer. This is the only way I've found which takes into effect all physics materials and 2d effectors. There are much more performant ways to calculate trajectories, but they're much simpler.
Alexandr K
Hi @Tarodev. What are you using for the 3d models in your examples? is it specific shaders? or preset that you imported from the unity assets store? thanks
Nauval Game
I hope this channel uploads more game development tutorial videos like brackeys, because I really like your previous tutorial videos.
More coming, stay tuned 😊
Great tutorial - is there any way to stretch out the prediction for a longer time without slowing down framerate? I'd be happy if I could do it at the sacrifice of line position draws but I can't seem to have any success extending the prediction before I hit framerate issues
I haven't tried this, but maybe double the time step each iteration? I actually don't know how it works under the hood though and chances are it's calculating every step regardless, but try that.


let's make a trajectory line which calculates rebounds and even takes the
bounciness and friction level of your object's materials into account
let's get into it so first let's start a new script let's
call this projection okay open it up
and the first thing we're going to do is create a new scene to perform our
simulations on uh which will be overlaid on the top of our ones so let's create a
new method here called uh creates we'll call it physics scene
and then in here we will create the same so uh
simulation scene let's call it will be equal to and we need scene
manager here so unity engine scene management
will be able to scene manager dot create saying
and let's call this just simulation it's just the name of the scene and it really
doesn't matter and for the parameters we will do new create scene parameters and
we'll use uh 3d um actually we will make this a private
variable as we'll be needing it and then we'll also make another private
variable called um physics scene and this will be equal to simulation
scene.get physics scene
so the top one here is the actual saying and then this one is specifically the
physics of that same okay next step is to actually put objects in the
simulation scene so for example i've got these objects here
which all have colliders on them and they're all children of this obstacles
uh object here so i'm just going to loop through these children and then add them
into this new scene so let's create a serialized field here
so we can see this in inspector private transform and this will be the
obstacle's parent okay now let's loop through these
objects so this will be a an object and this will be
oops i'm looping over my obstacle parents
and i'll type transform cool okay so now we're looking through all the children
and i'm going to spawn a new one so let's call this a
ghost dodge and we'll instantiate it and the prefab for this will just be the
object uh this child's game object just
grabbing the object the object and just spawning them
and then actually we need to spawn in the same location so we'll say obj dot
transform dot position and then obj uh rotation it's already transformed so
we don't need to access it like that and now we need to
throw it over to the new scene so scene manager move object to scene
and we'll send in the ghost objects and then the scene will be the simulation
scene cool so now we are creating these scenes
sorry the same grabbing the physics scene and then chucking all the objects
that we want in that scene over to it um and also uh when we do this because
both of the scenes are actually overlaid on top of each other we can actually see
these objects that we're spawning in the other scene so what we can do here is
ghost object get component and grab the renderer whether it's a
mesh renderer or a skinned mesh renderer or whatever this is the base class so it
should work enabled equals false so we're just
turning that off cool
so in our start function let's actually call this
creat holy moly create physics scene okay so before we continue let's
actually see if that's working so go across to our scene and on my canon i'm
going to attach the projection script and it's asking for the obstacle's
parents i'm just gonna put that there um yep press play and we'll say the
simulation scene has been uh created and it's got all of our game objects
okay so now that we've got our physics same let's actually run a simulation on
it now i've got this ball script here
uh and basically it's just you know it's doing some sound some uh particle
effects when it hits something uh but most importantly it's got this init
function here that as soon as we spawn we call this and we send in our velocity
and we'll just uh launch the ball we'll grab our rigid body and add force to it
so let's make a function here on our projection let's call this public void
uh simulates trajectory it's a pretty fitting name and this will
take in my ball ball prefab it will take in the position that we're wanting to
start it so this will be the uh the barrel of my cannon for example
and also the velocity that we're shooting it
cool okay so the first thing we need to do is
spawn the ghost object actually so we can just pretty much copy this
and just send in the uh details so the position and it's a
cannonball i don't really care about the rotation so quaternion rotation i'm
gonna grab the renderer and disable it and then
send in adjust the game object like that cool so now we've got our cannonball in
the other script and this is actually very repetitive so uh probably best to
put in a function uh for another time though so now that we've got it let's uh
shoot our ball so uh as i said i've got a function on my ball a net that just
adds the force so we can just say whoops ghost object dot init
and send in our velocity okay so now that we've got this ghost
cannonball and it's flying through the physics scene what we're going to do is
shoot forward x amount of physics frames and on each
one of those physics frames we're going to take note of where the ball was and
then we can actually plot that on our line renderer so let's grab a few uh
variables here so this will be a private line renderer
and let's call this line and then another one called
um this will be in an in sorry and this will be max physics
frame iterations
pretty self-explanatory name so then now let's set our line um
position count and this will be equal to our max
max iterations okay so now let's loop over for the
amount of our physics frames that we're going to do
and we're going to now use our physics same that we created a reference to
earlier and we're going to say simulate now we
want to simulate whatever we've got our max frame iteration set to we want to we
want to simulate that many physics frames in the future so we can just say
time dot fixed delta time so uh every single time this is called it's going
one uh physics update in the future for example
now we've done one physics frame update so now we can set our very first line
position to wherever the ball is at this very moment so we can say line dot set
position and it's going to be uh i for the uh
position index and our ghost object.transform.position
so let's say that this is defaulted to 100
for example so every single time that this is called we're going to predict
100 frames into the future and set our point there and then uh even though that
this poor little ball only just arrived into the world we are going to destroy
it straight away so it's not even going to to be honest we don't even need to do
this because it's not even visible for a whole scene uh for a whole frame we're
just going to delete it straight away um and i think that should be good
so let's head back into unity and on our canon we now need a line so
let's make a line renderer and let's reduce the thickness just a
little and for the material i have actually got a line material here which
will i i'll include in the uh in the description um i think that should be
good let's just see yeah
yep cool okay so our canon let's just remove the position
counts um
send that in set the iteration count to 100. okay so now we need to actually
call this simulate trajectory because right now nothing's calling it so it's
not doing anything so on my canon script so i haven't shown you this but i've got
this hidden here because it's not it's out of scope basically it's just you
know turning left and right up and down and pressing spacebar to shoot i will
include it in the description but yeah out of scope of this tutorial
let's call our projection so let's make a
serialized field private projection grab a reference to it
and then let's call it so projection.simulate trajectory and this
takes in the prefab so down here i've got this prefab reference so let's send
that in and where we want to actually start the uh simulation so on my canon
i'll just show you i've got this uh barrel and spawn right
here so that's where i want to spawn my ball so let's send in the bolt spawn
start position and the force will be uh ball spawn
all spawned up forward obviously we're wanting to um
shoot the ball forward uh times our force which i've got here okay
pretty simple stuff let's go back
and try that out so press play
and once it's saying object reference not set to an instance
because we haven't set our trajectory so let's send that into the canon
and press play and there we go aha so as you can see uh
it's like there's some phantom cannon balls right now and
hitting the ground we obviously don't want these to spawn so let's clean this
up a little bit um
on our ball let's actually send in boolean
is ghost and if they are indeed a ghost
is ghost equals is ghost just make that field there if is ghost
damn it is ghost then let's just return we don't we don't want to spawn these
effects here and so then in our ghost we'll say is ghost
true but then in our canon
we'll say is ghost false
okay let's try that out press play and there we go so no more um pucks on
the ground and the ball follows our projection line
perfectly obviously until it hits something that's not in the simulation
so these broken boxes are not in the simulation um
but yeah so the good thing about this is that it actually takes into account the
uh bounciness of the materials or the friction of the materials and puts that
into the simulation whereas if you were doing this uh in just a matthew way
which i have done in the past you would not well you could but it would be a
significantly larger effort to try and allocate for all the different material
types so that's one definitely good thing
about this and to be honest it's pretty damn easy it's not it's not that much
code pretty much just that and then calling
it and you've got yourself a prediction line so i hope this came in handy i hope
you had fun watching it and i'll see you next time bye
okay so i've just had another thought what if you want to actually move your
objects around in the scene uh if you're moving your main object here that does
not mean that your physics scene object is moving so what you could do
is uh when you create these objects uh let's say let's make this a private
uh dictionary and this will be of type game objects
and the key will be game object and the values will also be game object and this
will be sponge spawned objects because new dictionary
now what we're going to do here is actually update the physics object
location every like whenever the uh the actual object moves so that could
actually probably be pretty expensive so what i'm going to do is only grab the
objects that are not marked static so let's go here if
ghost object is static yeah
that is not static sorry spawned objects add and here we're going
to put in as the key the real object and then in here the ghost
object cool and then i'm going to make an
update function now we want to actually loop through
these objects and update the values position according to the keys position
so for each um it's going to be that collection and
we're going to say um item dot value dot position no
transform.position equals item dot key dot transform.position
um and that's actually horrible so let's let's change this to transform
transform transform transform transform just that and this one transform so now
we don't have to say that every time uh dot position and then this will be
the rotation just in case you're rotating it as well
so now that should um update the locations and we could just
simulate that pretty simply actually we need to make uh something
static so let's actually make these all static
and then let's just turn this one to non-static so now if we press play
and we put that up there if we actually move this one now
yep there we go but
as all the other ones are static if we move this one uh we can't because it's
static so that uh put a damper on that one so there we go um
yeah just a little extra chip just in case