Can I change an object's movement to match the angle of a wall it's touching?

Hello to all! I’ve been struggling with this issue for a few weeks now, so hopefully someone will be able to point me in the right direction to solve it.

I have a player character with a sphere collider and a custom movement script. The object has a Rigidbody for detecting collisions, but I’ve turned off the Rigidbody’s ability to affect position or rotation so I can keep tighter control on it. This unfortunately means I have to reinvent a few wheels, but so far only one thing has really eluded me.

My project is built as a 3D game with what is basically 2D movement along the X and Z plane–the floor is absolutely flat with no grooves or slants. I use a sphere cast to look for walls and obstacles the player shouldn’t be allowed to pass through and restrict movement so they stop right in front of it. If the player isn’t moving directly toward the wall, I want them to move along the surface of it.

For the most part, the character only has to worry about moving up against flat walls facing the four basic directions. I can handle this well enough if the player tries to move diagonally along them, changing it so only the X or Z movement actually goes through. My trouble is coming up when I have an angled wall that the player wants to move toward.

Let’s say I have a wall at a 45 degree angle and the player is trying to move up against its lower right side. What happens currently is that my sphere cast detects the wall and stops the movement short so the player stops when touching the wall. If the player tries to move up from there, nothing will happen because it still detects that the wall is there. They need to explicitly move up and to the right so the sphere cast won’t detect the wall in order to continue moving along.

What I want to happen is for the player to move against the wall, moving up and to the right even though their input is only for up. I have some ideas for what to do with their movement speed when this happens that I can figure out, but the big thing I need that I can’t figure out is the direction the player should be moving (that is, the direction that’s parallel to the surface of the wall they’re touching). I’ve attempted to do a few things with cross products to get the correct direction, but it’s really out of my league and I can’t tell how close or far I am with this math.

One other thing worth mentioning is that the object the player controls does not rotate. The character model will face different directions just fine, but the actual root object the player is controlling always has a rotation of Quaternion.Identity. (The camera is also at a fixed angle in this game, so this makes it easy to control no matter which way the player is facing.)

Does anyone have any experience with changing direction along a surface like this? If I really really need to learn cross products to make this work then I will, but I’m okay with seeing a solution I don’t understand and figuring it out over time by looking at it. If anyone can tell me what to do with this or point me in the right direction, I would really appreciate it!

After getting some advice, I ended up finding the solution I needed. I’ll post it here in case anyone with a similar issue needs to know about it.

In my case, it turns out that every wall I need to worry about uses a Box Collider. This means that it has flat surfaces and I don’t need to worry about any curves for this particular issue. When I detect an object in my sphere cast, I can call that object’s Transform.forward and Transform.right (and their negatives) to find the four possible directions a surface is facing.

Then I can check the angles between the original direction I want to move and each of the four angles and remove any that are more than 90 (these would be moving against of the intended direction). This should remove two, and I can do another quick sphere cast in the remaining directions looking for the same object the original collision was with–one will most likely collide with it and the other won’t. The clear one will be the final direction I’ll end up moving.

Just to add a feel for friction, I multiplied the original distance moved by (90 - X) / 90, where X is the angle between the original intended direction and the new direction. The you are to walking straight against a wall, the less distance you’ll actually move.

Hopefully this helps someone, because it took me plenty long to come across it!