ISSUE#1 경사면에 박혀서 안 움직임

SOLVE.

private void SlopeCheck()
{
    RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, detectDistance, groundCheckLayer);
    RaycastHit2D frontHit = Physics2D.Raycast(frontChecker.position, frontChecker.right * transform.localScale.x, 0.1f, groundCheckLayer);

    if (DebugMode)
    {
        Debug.DrawLine(frontChecker.position, frontChecker.position + frontChecker.right * transform.localScale.x, Color.blue);
        Debug.DrawLine(hit.point, hit.point + perp, Color.red);
        Debug.DrawLine(hit.point, hit.point + hit.normal, Color.blue); 
    }
    
    if (hit || frontHit)
    {
        if (frontHit)
            hit = frontHit;  
    }
    perp = Vector2.Perpendicular(hit.normal).normalized;
    slopeAngle = Vector2.Angle(hit.normal, Vector2.up);
    isSlope = (slopeAngle > 10) ? true:false; // 조건을 ==0 으로 설정시 정밀도가 떨어짐
}

Untitled

플레이어의 아래와 그 살짝 앞방향으로 Raycast 해서 수직 벡터를 구함.

Untitled

  if (isSlope && isGround && slopeAngle < maxAngle)
  {
      rigid.velocity = moveDir.x * perp * -1 * moveSpeed;
  }

경사면일 때는 그 수직 벡터 만큼 곱해준 방향으로 이동 시켜줌.

상태패턴으로 분리하고나서는 RunState에서 다음과 같이 진행함, SlopeCheck는 바닥에 있을때만.

 public override void Update()
    {
        SlopeCheck();
    }

    public override void FixedUpdate()
    {
        if (!player.isSlope)
        {
            if (player.moveDir.x < 0 && player.rigid.velocity.x > -player.maxSpeed)
            {
                player.rigid.velocity = new Vector2(-player.moveSpeed, player.rigid.velocity.y);
                effect.isFlip = true;
            }
            else if (player.moveDir.x > 0 && player.rigid.velocity.x < player.maxSpeed)
            {
                player.rigid.velocity = new Vector2(player.moveSpeed, player.rigid.velocity.y);
                effect.isFlip = false;
            }
        }
        else
        {
            player.rigid.velocity = player.moveDir.x * perp * -1 * player.moveSpeed;
        }
    }
    
    private void SlopeCheck()
    {
        RaycastHit2D hit = Physics2D.Raycast(player.transform.position, Vector2.down, 1f, player.groundCheckLayer);
        RaycastHit2D frontHit = Physics2D.Raycast(player.frontChecker.position, player.frontChecker.right * player.transform.localScale.x, 0.1f, player.groundCheckLayer);

        if (player.DebugMode)
        {
            Debug.DrawLine(player.frontChecker.position, player.frontChecker.position + player.frontChecker.right * player.transform.localScale.x, Color.blue);
            Debug.DrawLine(hit.point, hit.point + perp, Color.red);
            Debug.DrawLine(hit.point, hit.point + hit.normal, Color.blue);
        }

        if (hit || frontHit)
        {
            if (frontHit)
                hit = frontHit;
        }
        perp = Vector2.Perpendicular(hit.normal).normalized;
        slopeAngle = Vector2.Angle(hit.normal, Vector2.up);
        player.isSlope = (slopeAngle > 10) ? true : false;
    }

ISSUE #2 경사면의 끝에서 붕 뜸

Honeycam 2024-03-13 20-44-39.gif