How do I deal with slopes using forces? Unity2D

Viewed 35

I made this code for applying forces for movement following this tutorial.


    public static void XMove(float Dir ,float Speed ,Rigidbody2D rb ,float velPower ,float 
    acceleration ,float decceleration)
    {
        float TargetSpeed = Dir * Speed;
        
        float TargetSpeedDif = TargetSpeed - rb.velocity.x;
        
        float accelerRate = (Mathf.Abs(TargetSpeed) > 0.01f) ? acceleration : decceleration;
        
        float MoveDir = Mathf.Pow(Mathf.Abs(TargetSpeedDif) * accelerRate, velPower) * Mathf.Sign(TargetSpeedDif);

        rb.AddForce(MoveDir * Vector2.right);
    }

https://www.youtube.com/watch?v=KbtcEVCM7bw and it works how I want it, so I tried adding my new code for slope movement, because he got stuck on slopes, and it didn't work. I've been trying to get it to work using this, https://www.youtube.com/watch?v=QPiZSTEuZnw but, he either bounces as I move or still gets stuck. Slope Code.

private void SlopeCheck()
{
    checkPos = transform.position - (Vector3)(new Vector2(0.0f, colliderSize.y / 2));

    SlopeCheckHorizontal(checkPos);
    SlopeCheckVertical(checkPos);
}

private void SlopeCheckHorizontal(Vector2 checkPos)
{
    RaycastHit2D slopeHitFront = Physics2D.Raycast(checkPos, transform.right, slopeCheckDistance, gLayerMask);
    RaycastHit2D slopeHitBack = Physics2D.Raycast(checkPos, -transform.right, slopeCheckDistance, gLayerMask);

    if (slopeHitFront && canWalkOnSlope)
    {
        isOnSlope = true;
        slopeSideAngle = Vector2.Angle(slopeHitFront.normal, Vector2.up);

    }
    else if (slopeHitBack && canWalkOnSlope)
    {
        isOnSlope = true;

        slopeSideAngle = Vector2.Angle(slopeHitBack.normal, Vector2.up);
    }
    else
    {
        slopeSideAngle = 0.0f;
        isOnSlope = false;
    }

}

private void SlopeCheckVertical(Vector2 checkPos)
{      
    RaycastHit2D hit = Physics2D.Raycast(checkPos, Vector2.down, slopeCheckDistance, gLayerMask);
    
    if (hit)
    {
        
        slopeNormalPerp = Vector2.Perpendicular(hit.normal).normalized;            

        slopeDownAngle = Vector2.Angle(hit.normal, Vector2.up);

        if(slopeDownAngle != lastSlopeAngle)
        {
            isOnSlope = true;
        }                       

        lastSlopeAngle = slopeDownAngle;
       
        Debug.DrawRay(hit.point, slopeNormalPerp, Color.blue);
        Debug.DrawRay(hit.point, hit.normal, Color.green);

    }

    if (slopeDownAngle > maxSlopeAngle || slopeSideAngle > maxSlopeAngle)
    {
        canWalkOnSlope = false;
    }
    else
    {
        canWalkOnSlope = true;
    }

    if (isOnSlope && canWalkOnSlope && HorizontalValue == 0)
    {
        rb2d.sharedMaterial = fullFriction;
    }
    else
    {
        rb2d.sharedMaterial = noFriction;
    }
}
void FixedUpdate()
{
    Gcheck();
    Move(HorizontalValue, Crouch);
    SlopeCheck();
        
}
        #region Move & run
        

        if (isGrounded && !crouchFlag && !isOnSlope)
        {
            Controller.XMove(dir,Speed,rb2d,velPower,acceleration,decceleration);
        } else if (isGrounded && isOnSlope && canWalkOnSlope) 
        {
            float TargetSpeed = -dir * Speed;
        
            float TargetSpeedDif = TargetSpeed - rb2d.velocity.x;
        
            float accelerRate = (Mathf.Abs(TargetSpeed) > 0.01f) ? airacceleration : airdecceleration;
        
            float MoveDir = Mathf.Pow(Mathf.Abs(TargetSpeedDif) * accelerRate, velPower) * Mathf.Sign(TargetSpeedDif);
            
            float MoveDirX = MoveDir * slopeNormalPerp.x * MultSlope;
            float MoveDirY = MoveDir * slopeNormalPerp.y * MultSlope;

            rb2d.AddForce(MoveDirX * Vector2.right);
            rb2d.AddForce(MoveDirY * Vector2.up);
        }
        else if (!isGrounded)
        {
            float TargetSpeed = dir * Speed;
        
            float TargetSpeedDif = TargetSpeed - rb2d.velocity.x;
        
            float accelerRate = (Mathf.Abs(TargetSpeed) > 0.01f) ? airacceleration : airdecceleration;
        
            float MoveDir = Mathf.Pow(Mathf.Abs(TargetSpeedDif) * accelerRate, velPower) * Mathf.Sign(TargetSpeedDif);
            if (rb2d.velocity.y > 0 && !Input.GetButton("Jump"))
            {
                MoveDir = MoveDir * xJumpForce;
            }
            rb2d.AddForce(MoveDir * Vector2.right);  
        }else if (isGrounded && crouchFlag)
        {
            rb2d.sharedMaterial = noFriction;
            float TargetSpeed = dir * CrouchSpeed;
        
            float TargetSpeedDif = TargetSpeed - rb2d.velocity.x;
        
            float accelerRate = (Mathf.Abs(TargetSpeed) > 0.01f) ? acceleration : Crouchdecceleration;
        
            float MoveDir = Mathf.Pow(Mathf.Abs(TargetSpeedDif) * accelerRate, velPower) * Mathf.Sign(TargetSpeedDif);

            rb2d.AddForce(MoveDir * Vector2.right);  
        }

        

        if (isGrounded && Mathf.Abs(HorizontalValue) < 0.01f)
        {
            float amount = Mathf.Min(Mathf.Abs(rb2d.velocity.x), Mathf.Abs(fricAmount));

            amount *= Mathf.Sign(rb2d.velocity.x);

            rb2d.AddForce(Vector2.right * -amount, ForceMode2D.Impulse);
        }


        Vector3 CurrentScale = transform.localScale;

        if(Right && dir > 0)
        {
            transform.localScale = new Vector3(1.4f, 1.4f
            , 1);
            Right = false;
        }

        else if (!Right == dir < 0)
        {
            transform.localScale = new Vector3(-1.4f, 1.4f, 1);
            Right = true;
        }

        

        //2 Walk 4 Run
        Anime.SetFloat("VelocityX", Mathf.Abs(rb2d.velocity.x));
        Anime.SetFloat("VelocityY", Mathf.Abs(rb2d.velocity.y));

        #endregion
    }

}
0 Answers
Related