- Home /
Rotate vector A around vector B until it is perpendicular to vector C
I am creating a custom character controller that uses rigidbody physics to move around. At the moment, I can accurately calculate an acceleration vector that will move the player around, based on their inputs (WASD, shift, control), on the horizontal plane. The problem I am trying to overcome now is how to get them to move up and down slopes realistically. At the moment, the acceleration vector is only horizontal. What I am trying to do is get the normal of the terrain plane that the player is standing on (C), and rotate the acceleration vector (A) around the player's local x axis (B) until it is perpendicular to the normal (C).
I'm pretty sure the solution will involve cross/dot products but if this is a solved problem, there is no point me burning brain cells over it!
Is this a 2D game, where motion is confined to a single plane?
If so, the slope of a collider beneath a given point can be found using a raycast "down" at the collider. The angle between the hit.normal and the world "up" will give you a meaningful value about your slope, which you can use to select the ideal coefficient of force to achieve the behavior you want.
While I could work out exactly what you ask for, I don't think that is the right solution. Given a forward vector of movement (F) parallel to the characters XZ plane, if you have a slope, I think you want to do this:
F = Quaternion.FromToRotation(transform.up, slope.normal) * F;
Answer by Bunny83 · Nov 04, 2014 at 04:38 AM
Well, that's actually pretty easy ;) Just do those 3 steps:
project your acceleration vector onto the (normalized) ground normal.
subtract that projected vector from your acceleration vector
normalize the result and multiply it with your original length.
Something like that:
//C#
Vector3 AlignToGround(Vector3 groundNormal, Vector3 acceleration)
{
//groundNormal.Normalize(); // usually the surface normal is already normalized if not this line is needed
var V = Vector3.Project(acceleration, groundNormal);
V = acceleration - V;
return V.normalized * acceleration.magnitude;
}
Answer by UncleGus · Nov 23, 2014 at 08:57 PM
Thanks for your answers, here's how I ended up doing it.
Vector3 velocityRightVector = Vector3.Cross(hit.normal, rb.velocity);
Vector3 newVelocityVector = -Vector3.Cross(hit.normal, velocityRightVector);