Rotating to match surface normal makes object change its direction

Hello! I’ve been practicing some time making a 3D platforming game, including some basic physics.

I’m trying to do a wall jump mechanic. Basically, if the object in question detects that there is ground above him, if I press the jump button it will rotate to match the ground’s normal.

The problem I’ve got it’s that when I try to do this, the direction also changes, and starts to walk in the opposite direction that I want the object to move.

YouTube video that shows the problem

private void SlopeRotation()
        {
            if (isGrounded || !rotateToGround)
            {
                if (isGrounded || isJumping)
                {
                    waitAndRotate = waitRotationTime;
                }
                groundNormal = ray.normal;
                
                slopeRotation = Quaternion.FromToRotation(transform.up, groundNormal) * transform.rotation;
                transform.rotation = slopeRotation;
                //rb.MoveRotation(slopeRotation);

                if ((transform.rotation == slopeRotation) && !rotateToGround)
                {
                    Debug.Log(groundNormal);
                    rotateToGround = true;
                }

                Debug.DrawRay(ray.point, ray.normal * 2, Color.blue, 1);
            }

            else if (!isGrounded && !isJumping)
            {
                if (waitAndRotate <= 0f)
                {
                    rb.MoveRotation(Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(0f, transform.rotation.eulerAngles.y, 0f), slopeRotationSpeed * Time.deltaTime));
                }
                else
                {
                    waitAndRotate -= Time.deltaTime;
                }
            }
        }

Well, this is kinda expected when you rotate an object 180°. RotateTowards always chooses the shortest path to rotate. However a 180° rotation does not have any specific path that is shorter as all directions are equally far. Think of the shortest route from the north pole to the south pole. The direction you walk doesn’t matter as all paths are equally long. Instead of using FromToRotation you can simply use lookRotation. Since you probably want to be perfectly aligned with the normal we can not simply pass the normal as up vector in LookRotation as it would keep your forward axis perfectly aligned and not the up vector. However we can simply “flatten” your forward vector to be parallel to the ground surface. That way we have a new forward vector and can use the new normal as up vector

var fwd = Vector3.ProjectOnPlane(transform.forward, groundNormal);
slopeRotation = Quaternion.LookRotation(fwd, groundNormal);