I’m working on an ice hockey game and right now I want to make the Pass() function.
Currently, I just succeed in simply moving the puck : rb.velocity = Vector3.forward * 20.
My puck goes forward, and the drag and friction make it stops after a while. It collides well with everything in the path.
My problem is that now, I want to controle it more. And there is my problem. How can I calculate the velocity I need to apply to the puck, for it to reach it’s target at some precise “speed”.
Let’s take an example :
My puck is at Vector3(0,0,0);
My target is at Vector3(0,0,60);
My puck drag is 0.5;
My puck and ice frictions are at 0.001;
What should be the initial velocity for the puck to reach the target at a magnitude of 5 ?
N.B: after that, I’ll have to find a way to calculate it without the drag/friction, but with the gravity. (a Shot in the air). I’ve seen some subjects covering this part, but not taking into account the final speed.
Honestly, this is a very tough problem to get actually right, because you’ll basically have to simulate all the physics frames in between.
You can make some approximations, though. It’s possible to work backwards and math this out using integrals and calculus - I honestly can’t recall the relevant math right now, sorry, but I know it involves integrals.
I think it’s fair to say that you have a finite range of distances you’ll be using this for, right? What might be the best way to do this will be to create an AnimationCurve, where its “time” represents your distance. work out by trial and error at different speeds, how far away the puck gets before its velocity hits 5, and just manually build your “initial speed” curve that way.
It’s solvablable analytically for a given set of initial conditions. It’s one dimensional which makes it easier. Unity complicates it by using a discrete simulation instead of a continuous one. But that’s solvable too. You can probably google the solution to the intergral.
An analytical solution has some benefits, mainly that it will be valid no matter what you change the properties of your Rigidbody too.
An empirical approach like this is probably easier to set up. The downside is it needs to be rerun every time you change game parameters. Not a huge deal if you automete the process.
1- About precision and being actually right : that’s not really a problem. The mechanics of passing a puck involves a human behaviour, and human are not 100% precise. I also need to make it “not so precise”.
2- The animation curve / empirical approach seems fair enough for me. I’ll try to use some integrals calculus to get a decent result. If I fail, I can still go with your way
By the way, thanks again for your time.
EDIT.
For those who are interested, here is the “final” code :
void Pass() {
float desiredFinalMagnitude = 20;
Vector3 dest = new Vector3 (Target.position.x, 0, Target.position.z);
float distance = Vector3.Distance(dest, this.transform.position);
float speedNeeded = distance / 4 + desiredFinalMagnitude; // 4 is an arbitrary value which suits well my friction / drag
Vector3 direction = (dest - this.transform.position).normalized;
rb.velocity = direction * speedNeeded;
}
This is how drag is represented in mechanics, which is exactly the sort of maths you’re employing to solve your problem. It’s also good programming practice, as you can now put a field in the inspector and change it as you please!