Player Attack 기능 만들기

devKyoun·2024년 10월 16일
0

Unity

목록 보기
8/27

마우스 왼쪽 버튼을 누를 시 플레이어가 공격을 하는 기능을 만드려고 한다
PlayerManager.cs 에서 inputSystem을 통해 Attack 입력을 받고 PlayerInteractHandler.cs에서 해당 Attack 처리를 해준다

PlayerManager.cs

{...}

  void Update()
  {
  	  Graviry, Ground Check
      
      Move
	 ****************************
      if (_input.IsAttack())
      {
          interactHandler.Attack();
          _input.AttackInput(false);
      }
     *****************************
   }

{...}

PlayerInteractHandler.cs

public class PlayerInteractHandler : MonoBehaviour
{
    private Animator animator;

    private int animIDAttack;

    private void Awake()
    {
        animator = GetComponentInChildren<Animator>();
        animIDAttack = Animator.StringToHash("Attack");
        
    }

    public void Attack()
    {
        animator.SetTrigger(animIDAttack);
    }
}

이제 애니메이터로 가서 Attack 설정을 해줘야 하는데 연속 공격이 가능한가 확인하기 위해 Attack 애니메이션을 2개 추가 해 줬다


Attack 1 Transition 설정

애니메이터 파라미터에 Attack 파라미터 Trigger 형태로 선언하고 Attack이 눌렸을 시 이 Trigger를 활성화 해준다
Has Exit Time은 꺼줘야한다. 그래야지 Idle이든 Move 상태에서 Attack시 애니메이션이 즉시 실행되기 때문

Attack 2 Transition 설정


연속 공격의 구현을 우선 간단히 isAttacking 파라미터를 이용했다
isAttacking은 즉 현재 공격중인가? 를 판별한다
콤보 공격을 이 isAttacking 대신 isCanCombo? 같은 것으로 대처 할 예정이다
게임에서 콤보는 공격 시작과 공격 끝남 그 사이에 가능하다는 것 보다는 언제 클릭해야 다음 공격이 나가는지 그 콤보 타이밍이 있기 때문이다

Attack 3 Transition 설정 또한 Attack 2 Transition과 마찬가지로 했다 ( Attack 3 추가 했음 )


AnimationEventHandler.cs

public class AnimationEventHandler : MonoBehaviour
{
    private PlayerInteractHandler interactHandler;
    private Animator animator;

    private int animIDIsAttacking;


    void Awake()
    {
        animator = GetComponent<Animator>();
        animIDIsAttacking = Animator.StringToHash("isAttacking");
    }
	// 이 두가지 함수를 Attack1,2 애니메이션에 추가 해준다
    public void EnableAttacking()
    {
        animator.SetBool(animIDIsAttacking, true);
    }
    public void DisableAttacking()
    {
        animator.SetBool(animIDIsAttacking, false);
    }
}


Attack To Idle Transition

공격이 끝이나게 되면 Idle Walk Run Blend로 Transition 할 수 있게 해준다
이 역시 Has Exit Time을 체크해제 해줘야 한다


문제점

  • 플레이어 공격 도중 WASD 움직임이 가능해진다
    ➡️ PlayerManager.cs의 canMove를 AnimationEventHandler.cs 이벤트 함수에서 관리하기

    {...}
       public void EnableAttacking()
       {
       	// 프로퍼티 Get Set
           playerManager.CanMove = false;
           animator.SetBool(animIDIsAttacking, true);
       }
       public void DisableAttacking()
       {
           playerManager.CanMove = true;
           animator.SetBool(animIDIsAttacking, false);
       }
     {...}

    PlayerManager.cs

    void Update()
    {
    	{...}
        if (canMove)
        {
            playerMovement.Move();
        }
    
        #region Attack
    
        if (_input.IsAttack())
        {
            interactHandler.Attack();
            _input.AttackInput(false);
        }
        #endregion
        {,,,}
    }


  • 클릭을 매우 빠르게 할 시 공격이 끝났음에도 한번 더 트리거가 돼서 공격한다

    이는 AnimationEventHandler.cs의 DisableAttacking()함수에서 Attack에 대해 Reset Trigger을 해준다

    public void DisableAttacking()
    {
        playerManager.CanMove = true;
        animator.SetBool(animIDIsAttacking, false);
        animator.ResetTrigger(
    }

    근데 AnimationEventHandler에서 Attack Trigger에 대해 접근하는데 PlayerInteractHandler.cs에서도 Attack Trigger에 접근한다
    그래서 PlayerInteractHandler.cs는 AnimationEventHandler를 통해 Attack 기능을 처리 할 수 있도록 한다 ( 그래서 이름을 그냥 AnimationHandler로 바꿈 )

    public class PlayerInteractHandler : MonoBehaviour
    {
      private AnimationEventHandler animationHandler;
    
      private void Awake()
      {
          animationHandler = GetComponentInChildren<AnimationEventHandler>();
          
      }
    
      public void Attack()
      {
          animationHandler.Attack();
      }
    }
     public class AnimationEventHandler : MonoBehaviour
    {
      private PlayerManager playerManager;
      private Animator animator;
    
      private int animIDIsAttacking;
      private int animIDAttack;
    
      void Awake()
      {
          playerManager = GetComponentInParent<PlayerManager>();
    
          animator = GetComponent<Animator>();
          animIDIsAttacking = Animator.StringToHash("isAttacking");
          animIDAttack = Animator.StringToHash("Attack");
      }
    
      public void Attack()
      {
          animator.SetTrigger(animIDAttack);
      }
    
      public void EnableAttacking()
      {
          playerManager.CanMove = false;
          animator.SetBool(animIDIsAttacking, true);
      }
      public void DisableAttacking()
      {
          playerManager.CanMove = true;
          animator.SetBool(animIDIsAttacking, false);
          animator.ResetTrigger(animIDAttack);
      }
    }

결과

업로드중..

공격 도중 움직이지않고 공격 빠르게 해도 마우스 클릭이 뒤늦게 Trigger 되지 않음

생각하는 개선점

  • Idle의 애니메이션이 Move 애니메이션과 부자연스러워서 Idle 애니메이션 적합한거 찾기

  • 애니메이션 파라미터에 canCombo를 추가하고 AnimationHandler 함수를 통해 각 공격 애니메이션 마다 이벤트를 추가해서 좀 더 게임성 있는 공격 콤보를 구현하기

  • 공격 시 앞으로 조금 이동하기

  • 공격 시 일정시간 동안 카메라가 바라보는 방향으로 공격 방향을 바꿀 수 있게 하기
    전투 시 조작감의 편의성, 게임성이 더 오를 것으로 예상

profile
Game Developer

0개의 댓글