Vector parallel to collision surface

I’m trying to create a piece of code for my character (in C#) that would work on collision. The idea is to only keep the component of the speed parallel to the collision surface. It should only work on x-z plane, as y speed is handled separately.

old speed = normalized speed before collision
Sa = normalized vector, parallel to collision surface with y component = 0
Sa2 = projection of old speed onto Sa (dotSpeed in script)
new speed = speed after collision

The problem is getting the Sa vector, the one parallel to collision surface.

The rest of the code should look something like this.

    Vector 3 playerVelocitiy; //the one fed into controller.move

   void Update {

        if ((controller.collisionFlags & CollisionFlags.Sides)!=0)
			OnCollision(); // if we are touching sides run "OnCollision"

}


  
    void OnCollision {
    
    Vector 3 oldSpeed = playerVelocity;
    oldSpeed.y = 0;
    float magnitude = oldSpeed.magnitude;
    
    oldSpeed = oldSpeed.Normalize();
    
    //At this point I need to get vector Sa (normalized), the one paralel to the surface
    
    dotSpeed = Vector3.dot(oldSpeed, Sa); //dotSpeed == Sa2 on image
    Vector3 newSpeed = Sa * magnitude *dotSpeed;
    
    playerVelocity.x = newSpeed.x;
    playerVelocity.z = newSpeed.z;
    }

So basically my question is how to get the Sa vector, the one parallel to the collision surface normals? Any suggestions or ideas are welcome.

You actually do the reverse. You use the normal vector of the surface to project your velocity onto the normal. The resulting vector is the part of the velocity that should be removed from your actual velocity. So just subract that vector from your velocity and the resulting vector will be what you’re after.

I just read that you just need the x-z plane. Well that will work pretty much the same. Just zero the y component of all vectors involved so they are basically 2d vectors.

So it should look something like this:

// C#
Vector3 v = playerVelocity;
Vector3 n = collisionNormal;
v.y = 0;
n.y = 0;
n.Normalize();

Vector3 d = Vector3.Project(v, n);
v -= d;
playerVelocity.x = v.x;
playerVelocity.z = v.z;

Of course you can also simply “rotate” the normal vector by 90°, however just “some” vector parallel to the surface usualy doesn’t really help. Anyways, to rotate a 2d vector you just have to swap the two components and flip the sign of one of them. Which sign you flip determines the direction of the rotation. Which sign represents which rotation also depends on the space you work in. For example in screen space (0,0 is bottom left) it would be like this:

v = new Vector2(-v.y, v.x); // 90° counter clockwise.
v = new Vector2(v.y, -v.x); // 90° clockwise.

While in GUI space (0,0 is top left) it would be reverse:

v = new Vector2(-v.y, v.x); // 90° clockwise.
v = new Vector2(v.y, -v.x); // 90° counter clockwise.