How to calculate new direction along new surface? for gaming movement.
When player moves, in most games, he moves forward - regardless of any curved geometry under his feet. Thats what i want to achieve.
1) Initialy i have vector A (direction of movenent parallel to vertical surface S).
2) When i meet green surface with normal N, i need to change direction to vector B, which must have following conditions:
a) Vector B must be parallel to Green surface with normal N.
b) Vector B must stay parallel to S surface, which is just vertical surface.
how to do that?
// i have following variables:
Vector3 position; // lies on surface S.
Vector3 a; // initial movement direction.
Vector3 n; // normal of green surface.
// i need to calculate this new direction, along green surface, but only "vertical along", meening that must be conditions: b.x == a.x, b.z == a.z; All i need in other words, is just to change angle between Y axis (Vector3.up), so it would be along green surface.
Vector3 b = new Vector3(a.x, ??? , a.z); // ???
In other words, my character must flow up and down along his direction, but not "left-right". I.e. he must not change his "horizontal" XZ direction, he must change only Y direction, no matter on which surface he is moving on.
Other words - i just need vector of intersection of S and B surfaces, using only variables that i have.
Answer by Eno-Khaon · Mar 28, 2016 at 02:37 AM
Transforming a direction into another isn't actually too rough, fortunately.
If you consider the case of walking left and right (as your image suggests), transforming the vectors is really no different than any full, 3-dimensional change.
First, you'll want to know your inputs:
// C#
Vector2 controlInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
In this case, you might not even need the up and down, so a single float may suffice, depending on your intent.
Next, you need to determine which direction you will need to move. To do this, you'll probably want a rail to be forced to walk on (this can be done using something like a plane and Vector projections to stay locked onto it) but for simplicity, I'll simply base it on your back wall, "S", for now. This is a little more involved than a simple, single raycast if you want maximum accuracy, but this should get you started in the right direction:
// This assumes that the back wall "S" is a "plane" and, therefore, naturally has its face facing upward.
public Transform sPlane;
// ...
// ...
RaycastHit hit;
Vector3 movementRight = Vector3.right;
// Fire ray straight down at ground from character's orientation
if(Physics.Raycast(transform.position, -transform.up, out hit, 5.0f))
{
Vector3 hitNormal = hit.normal;
Vector3 hitTangent = Vector3.Cross(sPlane.up, hitNormal);
movementRight = hitTangent;
}
movementRight *= controlInput.x;
With that, your direction of movement is aligned to be parallel to the back wall "S", while following the curvature of the ground below the character.
It will take some fine tuning to get it quite the way you want, especially to deal with transitions. Your character will collide with a new surface on an inside edge before a centered raycast would hit it, so it would be best to iterate on the concept, but hopefully this will help you move forward with the design.
What are you talking about? i dont need "right" movement, and i dont need input control.
I have edited my 1st post, with new code, thats explaining more detail what i need.
Ahhhh...
If all you need are height changes while maintaining unhindered forward momentum, you're still going to need to know your intended direction of travel.
If you extrapolate a vector perpendicular to your movement and the ground (a or b), then you can rescale the vector back to the same x and z values afterward to maintain horizontal speed. As a safety measure against unusual angles, I'll also throw in projection against a plane aligned with A and Vector3.up for good measure:
Vector3 a = current$$anonymous$$ovement;
Vector3 n = normalOfB;
Vector3 s = Vector3.Cross(Vector3.up, a).normalized; // Perpendicular to A and world up
Vector3 p = Vector3.ProjectOnPlane(n, s); // Vector N flattened onto plane S
Vector3 b = Vector3.Cross(s, p); Vector B, normalized
b = (b * a.magnitude) / $$anonymous$$athf.Sqrt(b.x * b.x + b.z * b.z); // Eli$$anonymous$$ate Y axis to reset X and Z to their values in A exactly.
Omg, i dont know how you did it (yet), but its working!!! Thx alot.
i dont even actually need same X and Z for a and b, i thought i need, but that was my mistake. So last line of code - is unneeded. Thx again.
Your answer
Follow this Question
Related Questions
Confused about local, world coordinates when it comes to child objects... 0 Answers
Geometry data collection methods: Volume. 0 Answers
Make camera rotate around an object while keeping entire area visible 0 Answers
¿Como puedo hacer un Grid como Editor solo con ciertas medidas en 2D? (Como Geometry Dash) 0 Answers
Import colliders from Blender 1 Answer