Thanks :-) I did do some preparation work though, but yes I can code for a few hours without testing the code and have it work properly most of the time :-)
Thank you so much for this video. It was definitely something I never would have worked out on my own. Your explanation of everything was fantastic too. I was having trouble for a while with it not working, but ended up finding the issue, I had an "a" instead of a "c" in the quadratic equation which messed up the aim ever so slightly.
Great video! Using this for my third year university project where I'm implementing AI enemies with different levels of artificial stupidity. At the lowest level of intelligence enemies will just shoot at the direction of the player but at higher levels enemies will use the technique in this video to predictably fire at the player. Many thanks.
There seem to be two cases not covered in this video. I had cases with 2 positive roots, where to solve you actually have to take the min, not the max. And two negative roots, for which I haven't solved yet.
Interesting. Yes I didn’t test those cases I suppose it happens when the enemy is moving in the opposite direction or behind the player. I’d have to think this through, but I’m considering re-making this video one day and make it a bit better
hey, thank you for explaining this! there is little documentation on predictive aiming, but how would you translate it into 3d space? just by using vector3 instead of vector2? also, my "turret" is moving, how could you compensate for this?
If the target is moving in a straight line, you can convert this to a 2D plane in 3D space. I haven’t done this in any of my projects but that’s where I would start. Also, law of cosines is based on Pythagoras which also works in 3D space. Maybe one day I’ll do a 3D version of this tutorial
@@jeangodecoster couldn't you also just find the target's velocity and subtract the turret's velocity if it is moving? Then use that delta in the equation?
J'ai été très surpris par ce bout en Français xD. Je m'y attendais pas. En tout cas merci pour ce cours de math. Je vais essayer d'intégrer ca dans mon jeu :D
So good. My logic stopped when you said (dB = sA * (dA / sB)) is the "Same" as (= dA * (sA / sB))... I think if I would have understood that part I would've gotten the rest. But I copied that code, and that worked amazingly. But I really wish I would've understood it better. Thanks for sharing! Edit: I get that these 2 equations result in the same outcome, but I don't understand why we chose the other one here. :D
Thanks for the feedback. The reason I did that was simply to put dA on the left to make it clearer that we can isolate it as a factor. I suppose that, in trying to explain how I to the refactoring, I might have made things more confusing :-)
I feel a bit silly, but i can't figure out where the "1" came from. at 14:26 . how did "dA^2 - r^2*dA^2" turn into " (1-r^2) * dA^2" I'm sure I'm just missing some basic simplifying from many years ago aha.
Let’s replace dA^2 by something simpler to process: X That would make it X - X*r^2 I hope you see how that turns into X * (1-r^2) if you don’t then yeah there’s some catching up with math in order
@@jeangodecoster I want to thank you very much for this. I've been researching for months on how to get leading aim to work. Your code working on a 3d space game I've been doing. I found articles that showed a formula, or videos with the end result, but the step by step video on the theory is what let me figure out how to calculate the data. (I didn't have rigid body, so I needed to use , Vector3 TargetVelociy() { //target.transform.rotation = Quaternion.identity;
Vector3 newPos = target.transform.position; // each frame track the new position Vector3 objVelocity = (newPos - prevPos) / Time.deltaTime; prevPos = newPos; // update position for next frame calculation return objVelocity; } Not only is it working, but i actually understand.... 75? percent of what is going on here, and more tinkering with it will get me to 99. Thank you again!
How would I reference the position of the target's predicted motion (or the Vector3 position of "c" on the triangle) as opposed to the direction? I'd like to try to use this with a LookAt command Again awesome tutorial and thanks for your evil training
@@jeangodecoster well if you go to 10:12 in this clip from the game Halo: Reach, you’ll see an example of some space combat: ruclips.net/video/qLz7VxdZzGY/видео.html You’ll notice the player has two reticles: one in the center of their view, and one that slightly tracks ahead of enemy vessels to show where the player should be aiming if they want to get hits in. I’d like to recreate that second reticle
@@cutsceneentertainment6706 oh ok so you want to give the player some visual aid to predictively aim at so they can intercept the enemy's trajectory, right? I need to look back at my video but iirc we know the direction where we want to shoot and we also know the value of t (time) before projectile impact as well as the projectile's movement speed. So by doing direction.normalized * projectileSpeed you'll get the exact predicted position of impact.
I found this whole I was looking for it. Give you the time for impact and from there you can find the spot. From Scott Lembcke - Shooting a Moving Target // delta: relative position // vr: relative velocity // muzzleV: Speed of the bullet (muzzle velocity) // returns: Delta time when the projectile will hit, or -1 if impossible float AimAhead(Vector3 delta, Vector3 vr, float muzzleV){ // Quadratic equation coefficients a*t^2 + b*t + c = 0 float a = Vector3.Dot(vr, vr) - muzzleV*muzzleV; float b = 2f*Vector3.Dot(vr, delta); float c = Vector3.Dot(delta, delta); float desc = b*b - 4f*a*c; // If the discriminant is negative, then there is no solution if(det > 0f){ return 2f*c/(Mathf.Sqrt(desc) - b); } else { return -1f; } }
It's a bit weird though that he's doing Dot(vr, vr) and Dot(delta, delta) because the dot product of a vector with itself is simply the square of its magnitude. I wonder if Dot is more performant than calculating the magnitude but I would expect it to be roughly equivalent
@@jeangodecoster I'm trying to figure out why he is using these a b c. I change the code a bit so I can use it with rotation and moving with transform forward. But the AimAhead is the same...
@@jeangodecoster I think you and him do the same thing. He doesn't need to calculate the Cos because the Dot does have a Cos in the method... that's what I read from MathIsFun
@@jeangodecoster I actually used this in my 3d project for a rail shooter. It worked beautifully. If i remember correctly I just had to switch it to vector 3s and it handled everything normally.
I can vouch. My player has lost it's life many times to this mathematical formula.
If my game ever comes out, every innocent player that gets shot will have you to thank XD
Great tutorial!. It takes great skill to write code like this and run it and it works.
Thanks :-) I did do some preparation work though, but yes I can code for a few hours without testing the code and have it work properly most of the time :-)
Fantastic stuff, I'm 6 days from my deadlines and this saved my ass. This is the only video out there. Translated to 3D nicely too!
do you have discord? I'm having trouble transforming into 3d
Thank you so much for this video. It was definitely something I never would have worked out on my own. Your explanation of everything was fantastic too. I was having trouble for a while with it not working, but ended up finding the issue, I had an "a" instead of a "c" in the quadratic equation which messed up the aim ever so slightly.
Always happy to hear back from people who found my video helpful :-) have fun making games
Great video! Using this for my third year university project where I'm implementing AI enemies with different levels of artificial stupidity. At the lowest level of intelligence enemies will just shoot at the direction of the player but at higher levels enemies will use the technique in this video to predictably fire at the player. Many thanks.
Hey, I was just wondering, could you make a video on stopping the turret if there is no firing solution?
There seem to be two cases not covered in this video. I had cases with 2 positive roots, where to solve you actually have to take the min, not the max. And two negative roots, for which I haven't solved yet.
Interesting. Yes I didn’t test those cases I suppose it happens when the enemy is moving in the opposite direction or behind the player.
I’d have to think this through, but I’m considering re-making this video one day and make it a bit better
You are a genius, make everything easier to see, thank you very much for making this video, it helped me a lot.
hey, thank you for explaining this! there is little documentation on predictive aiming, but how would you translate it into 3d space? just by using vector3 instead of vector2? also, my "turret" is moving, how could you compensate for this?
If the target is moving in a straight line, you can convert this to a 2D plane in 3D space. I haven’t done this in any of my projects but that’s where I would start. Also, law of cosines is based on Pythagoras which also works in 3D space. Maybe one day I’ll do a 3D version of this tutorial
@@jeangodecoster couldn't you also just find the target's velocity and subtract the turret's velocity if it is moving? Then use that delta in the equation?
5:01
"it might seem confusing, but that's just to make it easier." xD
Thanks for the video. but i'm making a solar system game (for kids) I need to nail lead-targeting for circular orbits. Any help?
Hello, that's quite a step up. I don't think I can help with this without having to document myself extensively
Best youtuber ever!!!!!
J'ai été très surpris par ce bout en Français xD. Je m'y attendais pas. En tout cas merci pour ce cours de math. Je vais essayer d'intégrer ca dans mon jeu :D
It's Working ! Thank you again :)
So good. My logic stopped when you said (dB = sA * (dA / sB)) is the "Same" as (= dA * (sA / sB))... I think if I would have understood that part I would've gotten the rest. But I copied that code, and that worked amazingly. But I really wish I would've understood it better. Thanks for sharing!
Edit: I get that these 2 equations result in the same outcome, but I don't understand why we chose the other one here. :D
Thanks for the feedback.
The reason I did that was simply to put dA on the left to make it clearer that we can isolate it as a factor.
I suppose that, in trying to explain how I to the refactoring, I might have made things more confusing :-)
@@jeangodecoster I see your point! 👍
Thanks dude! Ur the best!
Dude, fuck me I spent way too long trying to solve this without your mathematical knowledge. Thanks mate
update: when you do this in 3D and your discriminant is negative, it doesn't work and there has to be a better solution.
it does not work, i checked few times, i did as on the video, projectiles always missed
I feel a bit silly, but i can't figure out where the "1" came from. at 14:26 . how did "dA^2 - r^2*dA^2" turn into " (1-r^2) * dA^2"
I'm sure I'm just missing some basic simplifying from many years ago aha.
Let’s replace dA^2 by something simpler to process: X
That would make it X - X*r^2
I hope you see how that turns into X * (1-r^2) if you don’t then yeah there’s some catching up with math in order
@@jeangodecoster I want to thank you very much for this. I've been researching for months on how to get leading aim to work. Your code working on a 3d space game I've been doing. I found articles that showed a formula, or videos with the end result, but the step by step video on the theory is what let me figure out how to calculate the data. (I didn't have rigid body, so I needed to use ,
Vector3 TargetVelociy()
{
//target.transform.rotation = Quaternion.identity;
Vector3 newPos = target.transform.position; // each frame track the new position
Vector3 objVelocity = (newPos - prevPos) / Time.deltaTime;
prevPos = newPos; // update position for next frame calculation
return objVelocity;
}
Not only is it working, but i actually understand.... 75? percent of what is going on here, and more tinkering with it will get me to 99.
Thank you again!
How would I reference the position of the target's predicted motion (or the Vector3 position of "c" on the triangle) as opposed to the direction? I'd like to try to use this with a LookAt command
Again awesome tutorial and thanks for your evil training
I need to look back at the video to understand your question :-) will take some time next week
@@jeangodecoster Ah thanks so much and no worries. I was just considering adding an assistive reticle for players to aim at.
@@cutsceneentertainment6706 can you draw me a mock-up of what you want to do?
@@jeangodecoster well if you go to 10:12 in this clip from the game Halo: Reach, you’ll see an example of some space combat:
ruclips.net/video/qLz7VxdZzGY/видео.html
You’ll notice the player has two reticles: one in the center of their view, and one that slightly tracks ahead of enemy vessels to show where the player should be aiming if they want to get hits in. I’d like to recreate that second reticle
@@cutsceneentertainment6706 oh ok so you want to give the player some visual aid to predictively aim at so they can intercept the enemy's trajectory, right?
I need to look back at my video but iirc we know the direction where we want to shoot and we also know the value of t (time) before projectile impact as well as the projectile's movement speed. So by doing direction.normalized * projectileSpeed you'll get the exact predicted position of impact.
I found this whole I was looking for it. Give you the time for impact and from there you can find the spot.
From Scott Lembcke - Shooting a Moving Target
// delta: relative position
// vr: relative velocity
// muzzleV: Speed of the bullet (muzzle velocity)
// returns: Delta time when the projectile will hit, or -1 if impossible
float AimAhead(Vector3 delta, Vector3 vr, float muzzleV){
// Quadratic equation coefficients a*t^2 + b*t + c = 0
float a = Vector3.Dot(vr, vr) - muzzleV*muzzleV;
float b = 2f*Vector3.Dot(vr, delta);
float c = Vector3.Dot(delta, delta);
float desc = b*b - 4f*a*c;
// If the discriminant is negative, then there is no solution
if(det > 0f){
return 2f*c/(Mathf.Sqrt(desc) - b);
} else {
return -1f;
}
}
Interesting use case for dot products. thanks for sharing.
It's a bit weird though that he's doing Dot(vr, vr) and Dot(delta, delta) because the dot product of a vector with itself is simply the square of its magnitude. I wonder if Dot is more performant than calculating the magnitude but I would expect it to be roughly equivalent
@@jeangodecoster Correct! I have no idea why that does it though. But it should work for 3d as well as 2d.
@@jeangodecoster I'm trying to figure out why he is using these a b c.
I change the code a bit so I can use it with rotation and moving with transform forward. But the AimAhead is the same...
@@jeangodecoster I think you and him do the same thing. He doesn't need to calculate the Cos because the Dot does have a Cos in the method... that's what I read from MathIsFun
The world is ruled by math. unfortunately I am bad at it
Could you do the same for the old blender 2.79 game engine?
I don’t know that engine, sorry
@@jeangodecoster Okay.
Genius it worked :)
i didn't understand a damn thing but listening to all this techno-jargon is entertaining with how absurd it sounds
love it 10/10
And now try it in 3D
It’s the same principle, and essentially the same math. Not a big deal to do.
@@jeangodecoster I actually used this in my 3d project for a rail shooter. It worked beautifully. If i remember correctly I just had to switch it to vector 3s and it handled everything normally.
@@jakesuninspireddevlog2894 Awesome, I'm really glad this can help out some people :-)
now do acceleration. good luck with that. You're better off using a iterative method.
Acceleration is an interesting challenge, however I see little practical interest for games. It’s just a rethorical problem