Force slope sliding in a platformer

I’ve started learning Unity a moth ago and so far I’m very excited.

I am testing out my own project outside of tutorials, to get familiar with things but (as you guessed it) I am stuck.

My platformer’s shape will be an octagon where at the bottom there will be some hazard that you have to jump over while sliding on the octagon’s slope. For the Slopes I’ve created a different Tilemap than the regular Ground to distinguish if I should slide or not ( not sure if this is the best solution tho) .

My Idea is the following:

As soon as the player touches the slope, it should trigger the slide animation and block all input except jump and also flip the sprite in the direction of the slide. I’ve tested a few methods so far but nothing works as expected. Mostly my animations toggle real quick between jump and slide state causing a stutter, or the player gets stuck at the top of the slope where it meets the vertical wall.

This is my PlayerMovement script ( the movement technique is from a udemy tutorial, idk if its the best one) . My player object has 2 colliders. One Capsule for the body and one box at the bottom for feet collision.

public class PlayerMovement : MonoBehaviour
{
    Vector2 moveInput;
    Rigidbody2D rb;
    Animator animator;
    BoxCollider2D feetCollider;

    [SerializeField] float runSpeed = 5f;
    [SerializeField] float jumpHeight = 10f;
    [SerializeField] float slideSpeedMultiplier = 1.5f;

    bool isGrounded;
    bool canDoubleJump;

    const string GroundLayer = "Ground";
    const string SlopeslsLayer = "Diagonals";

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        feetCollider = GetComponent<BoxCollider2D>();
    }

    void Update()
    {
        animator.SetFloat("yVelocity", rb.velocity.y);
    }

    void FixedUpdate()
    {
        GroundCheck();
        Run();
        FlipSprite();
    }

    void OnMove(InputValue value)
    {
        moveInput = value.Get<Vector2>();
        animator.SetBool("isDucking", moveInput.y < 0);
    }

    void Run()
    {
        Vector2 playerVelocity = new Vector2(moveInput.x * runSpeed, rb.velocity.y);
        rb.velocity = playerVelocity;

        bool playerHasHorizontalSpeed = Mathf.Abs(rb.velocity.x) > Mathf.Epsilon;
        animator.SetBool("isRunning", playerHasHorizontalSpeed);
    }

    void FlipSprite()
    {
        bool playerHasHorizontalSpeed = Mathf.Abs(rb.velocity.x) > Mathf.Epsilon;

        if (playerHasHorizontalSpeed)
        {
            Vector3 newScale = transform.localScale;
            newScale.x = Mathf.Sign(rb.velocity.x);
            transform.localScale = newScale;
        }
    }

    void OnJump(InputValue value)
    {
        if (value.isPressed)
        {
            if (isGrounded)
            {
                Jump();
                canDoubleJump = true;
            }
            else if (canDoubleJump)
            {
                Jump();
                canDoubleJump = false;
            }
        }
    }

    void Jump()
    {
        rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
    }

    void GroundCheck()
    {
        bool wasGrounded = isGrounded;
        isGrounded = feetCollider.IsTouchingLayers(LayerMask.GetMask(GroundLayer));

        if (wasGrounded != isGrounded)
        {
            animator.SetBool("Jump", !isGrounded);
        }
    }
}

My animator:

In general any feedback or suggestions about courses/ tutorials / documentation will be greatly appreciated!

Just make a second character controller for slopes: make this slope controller read the normal (perhaps with raycast) and slide the player along it, listening only for jump.

When you transition to or jump onto something flat, switch back to your other controller.

1 Like

Thank you for the suggestion!

I manged to make it work within the same controller with BoxCast and two methods, one for checking the ground collision and one for the slope.