오늘 학습 키워드

최종 팀 프로젝트

오늘 학습 한 내용을 나만의 언어로 정리하기

섬단에 큰 문제가 생김

  • 섬단이 벽을 뚫어버림;

  • 시도 1 - 이전위치를 기억해서 그것과의 거리가 너무 짧으면 그냥 Idle로 넘기게 함

public void LogicUpdate(PlayerController player)  
{  
    animRunningTime += Time.deltaTime;  
    float t = animRunningTime / attackAnimationLength;  
  
    if (animRunningTime > 0.2f)  
    {  
        prePos = curPos;  
        curPos = player.transform.position;  
      
        if (Vector2.Distance(prePos, curPos) < 0.001f)  
        {  
            player.PlayerMove.rb.velocity = Vector2.zero;  
            if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
            else player.ChangeState<FallState>();  
            return;  
        }  
    }  
      
    // 선형 보간하는 포지션을 만들어서 거기로 MovePosition    
    Vector2 newPos = Vector2.MoveTowards(startPos, targetPos, t * specialAttackSpeed);  
    player.PlayerMove.rb.MovePosition(newPos);  
  
  
    /*if (player.PlayerMove.isWallTouched)  
    {        player.PlayerMove.rb.velocity = Vector2.zero;        if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();        else player.ChangeState<FallState>();        return;    }*/    
    if (Vector2.Distance(newPos, targetPos) < 0.01f)  
    {  
        player.PlayerMove.rb.velocity = Vector2.zero;  
        if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
        else player.ChangeState<FallState>();  
        return;  
    }  
      
    if (Time.time - startStateTime > startAttackTime)  
    {  
        AnimatorStateInfo curAnimInfo = player.PlayerAnimator.animator.GetCurrentAnimatorStateInfo(0);  
  
        if (curAnimInfo.IsName("SpecialAttack"))  
        {   
            float animTime = curAnimInfo.normalizedTime;  
  
            if (animTime >= 1.0f)  
            {  
                if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
                else player.ChangeState<FallState>();  
                return;  
            }  
        }  
  
        if (animRunningTime >= attackAnimationLength)  
        {  
            if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
            else player.ChangeState<FallState>();  
            return;  
        }  
              
    }  
}
  • 시도 1 : 실패!

  • 시도 2 : (챗지피티의 도움) 이동하려는 위치로 선을 그어서 벽에 닿으면 그 직전까지만 움직이게

public void LogicUpdate(PlayerController player)  
{  
    animRunningTime += Time.deltaTime;  
    float t = animRunningTime / attackAnimationLength;  
  
    Vector2 newPos = Vector2.MoveTowards(startPos, targetPos, t * specialAttackSpeed);  
  
    curPos = player.transform.position;  
    Vector2 direction = (newPos - curPos).normalized;  
    float distance = Vector2.Distance(curPos, newPos);  
      
  
    RaycastHit2D hit =  
        Physics2D.Raycast(player.transform.position, direction, distance, player.PlayerMove.groundMask);  
      
      
    if (hit.collider != null)  
    {  
         player.PlayerMove.rb.MovePosition(hit.point - direction * 0.01f);  
        if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
        else player.ChangeState<FallState>();  
        return;  
    }  
      
    // 선형 보간하는 포지션을 만들어서 거기로 MovePosition    player.PlayerMove.rb.MovePosition(newPos);  
      
    if (Vector2.Distance(newPos, targetPos) < 0.01f)  
    {  
        player.PlayerMove.rb.velocity = Vector2.zero;  
        if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
        else player.ChangeState<FallState>();  
        return;  
    }  
      
    if (Time.time - startStateTime > startAttackTime)  
    {  
        AnimatorStateInfo curAnimInfo = player.PlayerAnimator.animator.GetCurrentAnimatorStateInfo(0);  
  
        if (curAnimInfo.IsName("SpecialAttack"))  
        {   
            float animTime = curAnimInfo.normalizedTime;  
  
            if (animTime >= 1.0f)  
            {  
                if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
                else player.ChangeState<FallState>();  
                return;  
            }  
        }  
  
        if (animRunningTime >= attackAnimationLength)  
        {  
            if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
            else player.ChangeState<FallState>();  
            return;  
        }  
              
    }  
}
  • 시도 2 : 성공!

패링 만들기

// AttackHitbox.cs
private void OnTriggerEnter2D(Collider2D other)  
{  
    if (Player.PlayerAttack.isStartParry)  
    {  
        if (other.TryGetComponent(out ICountable countable))  
        {  
            Player.PlayerAttack.successParry = true;  
            countable?.CounterAttacked();  
            Debug.Log("플레이어 패링 성공");  
        }  
        return;  
    }  
          
    if (other.TryGetComponent<IDamagable>(out var damagable)  
        && other.gameObject.layer == LayerMask.NameToLayer("Monster"))  
    {  
        damagable?.TakeDamage(Damage);  
        Debug.Log($"플레이어가 몬스터에게 {Damage} 만큼 데미지 줌");  
    }   
}

점프가 뭔가 어색함.

  • AddForce로 하다 보니까 뭔가 어색한 문제가 있었음
  • 그래서 MovePosition으로 해보는게 어떨까 라는 생각이 들어서 기존의 Jump 코드를 바꿔봄
public class JumpState : AirSubState  
{  
    private float minWallHoldTime = 1f; // 이 초가 지나야 벽 짚기가 가능함  
    private float elapsedTime;  
  
    private float jumpAnimationLength;  
  
    private float jumpSpeed = 1.2f;  
    private float jumpDistance = 4f;  
      
    private Vector2 startPos;  
    private Vector2 targetPos;  
    private Vector2 newPos;  
    private Vector2 curPos;  
      
    private float t;  
      
    public override void Enter(PlayerController player)  
    {  
        base.Enter(player);  
          
        var moveInput = player.Inputs.Player.Move.ReadValue<Vector2>();  
          
        player.PlayerAnimator.SetTriggerAnimation(PlayerAnimID.Jump);  
        player.isLookLocked = true;   
        elapsedTime = 0f;  
          
        jumpAnimationLength =   
            player.PlayerAnimator.animator.runtimeAnimatorController  
                .animationClips.First(c => c.name == "Jump").length;  
          
          
        startPos = player.transform.position;  
  
        if (moveInput.x == 0)  
        {  
            targetPos = startPos + (Vector2.up * jumpDistance);  
        }  
        else  
        {  
            targetPos = startPos + ((new Vector2((moveInput.x < 0) ? -1f : 1f, 1f)).normalized * jumpDistance);  
        }  
          
          
          
        if (!player.PlayerMove.isGroundJump) player.PlayerMove.isGroundJump = true;  
    }  
  
    public override void HandleInput(PlayerController player)  
    {  
        elapsedTime += Time.deltaTime;  
        var moveInput = player.Inputs.Player.Move.ReadValue<Vector2>();  
          
        if (player.Inputs.Player.Jump.triggered)  
        {  
            if(!player.PlayerMove.isDoubleJump)  
            {  
                player.ChangeState<DoubleJumpState>();  
                return;  
            }  
        }  
        if (player.PlayerMove.isWallTouched && elapsedTime >= minWallHoldTime)  
        {  
            player.ChangeState<WallHoldState>();  
            return;  
        }  
          
        if (player.Inputs.Player.NormalAttack.triggered && moveInput.y < 0)  
        {  
            player.isLookLocked = true;  
            player.ChangeState<DownAttackState>();  
            return;  
        }  
        if (player.Inputs.Player.NormalAttack.triggered && !player.PlayerAttack.HasJumpAttack)  
        {  
            player.isLookLocked = true;  
            player.ChangeState<NormalJumpAttackState>();  
            return;  
        }  
          
        if (player.Inputs.Player.SpecialAttack.triggered)  
        {  
            player.isLookLocked = false;  
            player.ChangeState<SpecialAttackState>();  
            return;  
        }  
        if (player.Inputs.Player.Dodge.triggered)  
        {  
            player.ChangeState<DodgeState>();  
            return;  
        }  
        if (player.Inputs.Player.Parry.triggered)  
        {  
            player.ChangeState<StartParryState>();  
            return;  
        }  
    }  
  
    public override void LogicUpdate(PlayerController player)  
    {  
        t = elapsedTime / jumpAnimationLength;  
        newPos = Vector2.Lerp(startPos, targetPos, t * jumpSpeed);  
  
        curPos = player.transform.position;  
          
          
        // 현재 위치에서 이동할 위치만큼 선 하나 그어서, 그게 벽에 닿으면 벽 끝에까지만 가고 상태 바뀌게함  
        Vector2 direction = (newPos - curPos).normalized;  
        float distance = Vector2.Distance(curPos, newPos);  
          
        RaycastHit2D hit =  
            Physics2D.Raycast(player.transform.position, direction, distance, player.PlayerMove.groundMask);  
          
        if (hit.collider != null)  
        {  
            player.PlayerMove.rb.MovePosition(hit.point - direction * 0.01f);  
            player.ChangeState<FallState>();  
            return;  
        }  
          
          
        player.PlayerMove.rb.MovePosition(newPos);  
          
        if (Vector2.Distance(newPos, targetPos) < 0.01f)  
        {  
            player.PlayerMove.rb.velocity = Vector2.zero;  
            player.ChangeState<FallState>();  
            return;  
        }  
          
          
          
        if (!player.PlayerMove.isGroundJump)  
        {  
            player.PlayerMove.isGroundJump = true;  
            return;  
        }  
        player.PlayerMove.Move();  
        if (player.PlayerMove.rb.velocity.y < 0)  
        {  
            player.ChangeState<FallState>();  
            return;  
        }  
    }  
  
    public override void Exit(PlayerController player)  
    {  
        base.Exit(player);  
        player.isLookLocked = false;  
    }  
}
  • 이랬더니 1단 점프는 자연스러운데 2단 점프는 어색함. (2단 점프도 이렇게 바꿨음)
  • 그래서 2단 점프만 AddForce를 해볼까 고민 중
  • 그러다가 그냥 1-2단 점프는 AddForce를 하고 벽점프를 바꿔보기로 함
// WallJumpState.cs
public class WallJumpState : AirSubState  
{  
    private float wallJumpStartTime;  
    private float wallHoldAbleTime = 0.5f;  
    private float startFallTime = 0.2f;  
      
    private float animRunningTime = 0f;  
    private float wallJumpAnimationLength;  
    private float wallJumpSpeed = 5f;  
    private float wallJumpDistance = 8f;  
  
    private Vector2 wallJumpDirection;  
    private Vector2 startPos;  
    private Vector2 targetPos;  
    private Vector2 newPos;  
    private Vector2 curPos;  
      
    private float t;  
  
    public override void Enter(PlayerController player)  
    {  
        base.Enter(player);  
        // Debug.Log("벽점!");  
        // 벽점할 때에는 벽 반대방향 봐야됨  
        player.PlayerMove.ForceLook(!player.PlayerMove.lastWallIsLeft);  
        player.isLookLocked = true;  
        // 벽점했으니까 강제로 벽 터치 취소  
        player.PlayerAnimator.ClearBool(); // WallHold 끄려고  
        player.PlayerMove.isWallTouched = false;  
        player.PlayerAnimator.SetTriggerAnimation(PlayerAnimID.WallJump);  
          
        wallJumpStartTime = Time.time;  
          
        animRunningTime = 0f;  
        /*player.PlayerMove.WallJump();*/  
        wallJumpAnimationLength =   
            player.PlayerAnimator.animator.runtimeAnimatorController  
                .animationClips.First(c => c.name == "WallJump").length;  
          
        wallJumpDirection = new Vector2((player.PlayerMove.lastWallIsLeft ?  1.5f : -1.5f),1f).normalized;  
        startPos = player.transform.position;  
        targetPos = startPos + (wallJumpDirection * wallJumpDistance);  
    }  
  
    public override void HandleInput(PlayerController player)   
    {  
        //if (player.Inputs.Player.Move.ReadValue<Vector2>().x != 0)  
        //{        //    player.PlayerMove.Move();        //    return;        //}  
        var moveInputs = player.Inputs.Player.Move.ReadValue<Vector2>();  
  
        if (player.Inputs.Player.Jump.triggered && !player.PlayerMove.isDoubleJump)  
        {  
            player.ChangeState<DoubleJumpState>();  
            return;  
        }  
  
        if(Time.time - wallJumpStartTime > wallHoldAbleTime && player.PlayerMove.isWallTouched)  
        {  
            player.ChangeState<WallHoldState>();  
            return;  
        }  
        else  
        {  
            player.PlayerMove.isWallTouched = false;  
        }  
          
        if (player.Inputs.Player.NormalAttack.triggered && moveInputs.y < 0)  
        {  
            player.isLookLocked = true;  
            player.ChangeState<DownAttackState>();  
            return;  
        }  
          
        if (player.Inputs.Player.NormalAttack.triggered && !player.PlayerAttack.HasJumpAttack)  
        {  
            player.isLookLocked = true;  
            player.ChangeState<NormalJumpAttackState>();  
            return;  
        }  
          
        if (player.Inputs.Player.SpecialAttack.triggered)  
        {  
            player.isLookLocked = false;  
            player.ChangeState<SpecialAttackState>();  
            return;  
        }  
        if (player.Inputs.Player.Dodge.triggered)  
        {  
            player.ChangeState<DodgeState>();  
            return;  
        }  
          
          
  
    }  
  
    public override void LogicUpdate(PlayerController player)  
    {  
        animRunningTime += Time.deltaTime;  
        t = animRunningTime / wallJumpAnimationLength;  
  
        newPos = Vector2.Lerp(startPos, targetPos, t);  
  
        curPos = player.transform.position;  
          
          
        // 현재 위치에서 이동할 위치만큼 선 하나 그어서, 그게 벽에 닿으면 벽 끝에까지만 가고 상태 바뀌게함  
        Vector2 direction = (newPos - curPos).normalized;  
        float distance = Vector2.Distance(curPos, newPos);  
          
        RaycastHit2D hit =  
            Physics2D.Raycast(player.transform.position, direction, distance, player.PlayerMove.groundMask);  
          
        if (hit.collider != null)  
        {  
            player.PlayerMove.rb.MovePosition(hit.point - direction * 0.01f);  
            if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
            else player.ChangeState<FallState>();  
            return;  
        }  
          
          
        player.PlayerMove.rb.MovePosition(newPos);  
          
        if (Vector2.Distance(newPos, targetPos) < 0.01f)  
        {  
            player.PlayerMove.rb.velocity = Vector2.zero;  
            if (player.PlayerMove.isGrounded) player.ChangeState<IdleState>();  
            else player.ChangeState<FallState>();  
            return;  
        }  
  
  
        /*  
        if (animRunningTime >= startFallTime)        {            if (player.PlayerMove.rb.velocity.y < 0)            {                player.ChangeState<FallState>();                return;            }        }*/                  
if (player.PlayerMove.isGrounded)  
        {  
            player.ChangeState<IdleState>();  
            return;  
        }  
    }  
  
    public override void Exit(PlayerController player)   
    {  
        base.Exit(player);  
        player.isLookLocked = false;  
    }  
}

학습하며 겪었던 문제점 & 에러

문제 1

  • 문제&에러에 대한 정의

분명 클래스를 만들었는데 라이더에서 인식을 못하고 자동완성도 안되는 사태가 있었다

  • 해결 방법

Preference > Registry Packages + Player Projects 체크 > Regenerate Project Files 했더니 해결됨