Trying to adjust movement to match the ground slope

I’m wanting to offset my movement to match the slope of the ground.

So if I’m walking up an incline the force applied in the direction of the slope, and not just forward.

Right now this is what I have:

    void Movement(){
        Vector3 input = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
        //input += groundSlope;
        input = input.normalized;
        if (isGrounded && !isSliding){
            myRigidbody.AddRelativeForce(input * Time.fixedDeltaTime * groundVelocity);
        }
        if (!isGrounded || isSliding)
        {
            myRigidbody.AddRelativeForce(input * Time.fixedDeltaTime * airVelocity);
        }
    }

Thanks!

edit: Just a heads up, the groundSlope variable is the normal of a raycast hit.

If i understand you want to align the player to the ground Normal.
you could use a Raycast to check the ground normal. sorry its just a pseudocode to illustrate what i mean.

Vector3 groundNormal;
isOnGround = Physics.Raycast(ray, out hitInfo, maxGroundDist, whatIsGround);
groundNormal = hitInfo.normal.normalized;
Vector3 projection = Vector3.ProjectOnPlane(transform.forward, groundNormal);
Quaternion rotation = Quaternion.LookRotation(projection, groundNormal);

Match the ground normal using MoveRotation()

rigidBody.MoveRotation(Quaternion.Lerp(rigidBody.rotation, rotation, Time.deltaTime));

Or better use Quaternion.RotateTowards() instead of the Lerp for more precision.
This when you’re grounded
ELSE

 groundNormal = Vector3.up;

and use the same projection…

Hope it matchs :slight_smile: what you want.

1 Like

I appreciate the help, but I’m not trying to align the player to the ground normal.

I’m wanting to adjust the player’s movement force to match the normal.

In other words, if I’m walking up a slope I don’t want to push the player’s rigidbody forward, I want to push it in the direction of the slope.

I have some very ugly code that does this in a pretty dumb way already, but I’m thinking there has to be a more elegant and simpler solution.

1 Like

you should maybe post this code, other people could help you.
Also what is your context? is the player a vehicle, a human model?.. Its not easy to move humanoids with forces realisticly…

1 Like

It’s for an FPS.

Give me a moment and I’ll post my trash code.

I’m already embarrassed to post this, so please be gentle. :smile::sweat_smile:

    void MovementInput(){
        input = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
        input = input.normalized;

        //Slope Movement Adjustment
        if (!isSliding)
        {
            RaycastHit slopeHit;
            if (Physics.Raycast(transform.position + (input * 0.5f) + (transform.TransformDirection(Vector3.up) * 1.5f), transform.TransformDirection(-Vector3.up), out slopeHit, 3f, layerMask))
            {
                input = (slopeHit.point - transform.position);
                if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0) input = input.normalized;
            }
        }
    }

    void Movement(){
        if (isGrounded && !isSliding){
            myRigidbody.AddRelativeForce(input * Time.fixedDeltaTime * groundVelocity);
        }
        if (!isGrounded || isSliding)
        {
            myRigidbody.AddRelativeForce(input * Time.fixedDeltaTime * airVelocity);
        }
    }

MovementInput is on Update, Movement is on FixedUpdate.

I can’t really look into code at the moment, but there is this Sebastian Lague video about climbing slopes. It is 2D though, but I believe it is easily adaptable into 3D. Hope this helps.

https://www.youtube.com/watch?v=cwcC2tIKObU

1 Like