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.

66802-pic2.png

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.