How do I get an object's velocity in one direction?
I am creating physics driven rockets fired by the player in a six-degrees-of-freedom game. When the player launches them they need to take on the ship's velocity so that they don't wind up behind the player if the ship is moving forward when they fire. Simply adding rocket.rigidbody.velocity = player.rigidbody.velocity
works, but it is virtually impossible to aim while moving with this enabled because it is difficult to account for your own vertical and lateral momentum.
What I need to do is only pass on the player's velocity in the direction they are facing (and hence the direction the rockets will be moving in). The player can potentially be moving and facing in any combination of directions. I've tried a number of things, but my vector math skills are really not that advanced and I'm not getting results. I would very much appreciate assistance.
Answer by elenzil · May 11, 2017 at 06:37 PM
this is a basic vector math question.
pulling the restated question from comments above:
allow me to restate the question as your interpretation is not what I had intended. I need to extract from the player's rigidbody.velocity only their speed in a particular direction.
this is called Vector Projection. You want the "Projection of the velocity vector onto the particular direction".
It's pretty easy to get.
Let's call the velocity vector vV and the other direction vector vD. You want to find vP, the projection of vV on vD. vP will be the dot-product of vD and the normalized vP vector, all times the normalized vP vector.
Vector3 vV; // velocity vector
Vector3 vD; // some other vector
Vector3 vDNorm = vD.normalized;
float dot = vV.Dot(vD);
Vector3 vP = vDNorm * dot;
you can also use Vector3.Project. in that case, be sure to normalize vD before passing it in.
if you just want their speed in the other direction (versus the portion of their velocity in that particular direction), that would be the dot-product value "dot" in the code, which is equivalent to the magnitude of the projected vector.
Thank you, that's exactly what I was after. I shall endeavor to understand better what is going on here. I need to get a better handle how to use dot products. In the meantime, however, it works perfectly. For the record, here is the code which finally worked for me:
rocket.rigidbody.velocity = Vector3.Dot(player.rigidbody.velocity,player.transform.forward) * player.transform.forward.normalized;
Once again, thank you very much.
awesome, glad that worked. i think you could simplify your code to this:
rocket.rigidbody.velocity = Vector3.Project(player.rigidbody.velocity, player.transform.forward);
Answer by JustJunuh · May 11, 2017 at 07:25 AM
Just so happens I've been working with vectors a lot recently. I might be able to help you but no guarantees here.
Ok so you said that you just wanted to change the direction with the velocity value of the rocket but NOT change the speed?
My apologies but I didn't perfectly understand what you wanted so I'm just gonna guess here.
So sit down, grab some popcorn, get a soda, and let me learn you about some vectors.
So essentially a vector is made up of two parts. A Direction and A Magnitude
The magnitude is the "speed" at which the object is moving.
The direction is..... fill in the blank.
If you wanted to use JUST the direction, I would recommend .normalized
or Normalize()
depending on the context. What this does is essentially set the vector's magnitude to 1 while maintaining its direction.
With its magnitude at one, you can multiply any speed value to that velocity and that will become its new magnitude.
On a side note, here's what vector math looks like.
At the end of the first vector, start to draw the second vector. The green vector is the new sum of the two. Notice how much larger the magnitude is and how the direction resembles neither of the original two.
The new direction is always a compromise between the two original vectors. The first vector was in Quadrant I while the second vector is in Quadrant IV. The resulting vector was directly in between QI and QIV.
The new magnitude will be greater based on how similar the directions are. In the example, the new magnitude could be larger if the directions of a and b were the same. Conversely, the new magnitude could be shorter if the directions of a and b were completely opposite (b would be overlapping a because it would be moving backwards on top of a thus shrinking the magnitude).
Maybe doodle on some paper and try to experiment with this so you can get a feel for how they work.
Well, hopefully you learned something today. Let me know if you need more help.
I appreciate the depth of your response, and the attempt to explain the theory, but please allow me to restate the question as your interpretation is not what I had intended. I need to extract from the player's rigidbody.velocity only their speed in a particular direction.
For example, if this was a 2D world and the player was facing directly down the x axis (1,0) and was moving at speed (2,1) their velocity.forward would be 2 even though the overall magnitude of their velocity is 3 (I think), because we are only interested in their velocity down the x axis. This would be very easy work out if the player was always facing down a world axis (since), but in this case they could be facing in any direction.
Another way to think about it is that I have temporarily solved the problem with rocket.rigidbody.velocity = player.transform.forward * player.rigidbody.velocity.magnitude
. Of course, this is inaccurate because if the ship is moving at velocity of 100 upwards, the rocket will be given a velocity of 100 forwards, but at this stage it is functional to continue designing.
I hope that is a bit clearer.
Answer by phxvyper · May 11, 2017 at 03:56 PM
If you're only worried about setting the velocity towards the direction that the player is facing, you can use the forward
value of the player's or object's transform via transform.forward
. This isn't in local coordinates either, its in terms of the world space, so setting
rigidbody.velocity = transform.forward
will indeed result in what you expect - the rocket will have the same forward
velocity as the player, heading in the same direction at the same speed - but it will not have local altitudinal or longital velocities.
Transform.forward
only returns the direction an object is facing, not its velocity along that vector.
Answer by JustJunuh · May 11, 2017 at 04:26 PM
So is this what you wanted?
If so, no need to set rocket velocity equal to player velocity. Do this. //Class for rocket //Somewhere in the class variable declarations area public Transform ship; //Set "ship" to the transform of your ship // Vector3 Scalar rocketvelocity = ship.forward * startSpeed; //Or ship.transform.forward idk
Ugh I hate the formatting here.
public Transform ship;
rocketVelocity = ship.forward * startSpeed;