본문 바로가기
스파르타 내배캠

스파르타 내배캠 Unity 3기 25일차

by LemongO 2024. 1. 27.

뭔가 고민이 많아진다... 뭔진 몰라도 많아진다...

 

 

 

그래도 일단 오늘은 칼국수 만들어 먹어야지 ㅋ

 

 


Player Shooting

 

공격 시스템이다.

이번 부분에선 내가 모르던 것들이 좀 나온 느낌이다.

수학적인 계산부분이긴한데 이런 것들을 이해하는게 재밌으니 조금 자세히 보도록 해야겠다.

 

 

일반적인 2D 연사 공격 시스템이라 하면

  • 마우스 좌클릭을 누르고 있는 동안엔 연속적인 공격이 가능하다.
  • 보고있는 방향으로 투사체가 발사된다.
  • 벽 or 몬스터 에게 닿으면 투사체가 사라진다. (데미지는 별개로)

간단한 흐름은 이런식이고 이번 강의에선 공격 시스템만 만들기 때문에 2번째 까지만 구현 되어있는듯 하다.

 

일단 공격 시스템도 InputSystem 을 적용할 것이니 그 부분을 먼저 보자.

 

공격은 마우스 좌클릭을 바인딩 해줬다.

 

public class PlayerInputController : TopDownCharacterController
{
    // 마우스 왼쪽버튼 Down & Up 할 때 마다 호출 됨.
    // 그래서 Fire는 Down 할 때 발동되는거니까 value.isPressed 를 이용해 Down 상태를 IsAttacking 변수 true에 사용한다.
    public void OnFire(InputValue value)
    {        
        IsAttacking = value.isPressed;        
    }
}

(강의 들으면서 주석 달아놓은건데 생각보다 잘 쓴거 같기도?)

 

OnFire 메서드에서 부모 클래스인 TopDownCharacterController 의 bool 프로퍼티 IsAttacking 에

마우스 좌클릭 press 했을 때 값을 할당한다. 즉, Down 시 true다.

 

그런데 지금 OnFire 함수의 경우 다른 Move Look 과 달리 Action 호출을 하지 않는다.

그럼 이 부분은 어떻게 해결한 걸까?

 

부모 클래스를 보도록 하자.

public class TopDownCharacterController : MonoBehaviour
{
    public event Action OnAttackEvent;

    private float _timeSinceLastAttack = float.MaxValue;
    protected bool IsAttacking { get; set; }
   
    protected virtual void Update()
    {
        HandleAttackDelay();
    }

    private void HandleAttackDelay()
    {
        if (_timeSinceLastAttack <= 0.2f)
        {
            _timeSinceLastAttack += Time.deltaTime;
        }

        if (IsAttacking && _timeSinceLastAttack > 0.2f)
        {
            _timeSinceLastAttack = 0;
            CallAttackEvent();
        }
    }
    
    public void CallAttackEvent()
    {
        OnAttackEvent?.Invoke();
    }
}

 

Attack 에 관련된 Action 은 가지고 있는것이 보인다.

전역 변수로 공격 딜레이시간(흐르는 시간)을 가지고 있고

아까 보았던 IsAttacking 프로퍼티로 공격가능한 상태인지 확인해준다.

 

HandleAttackDelay 메서드에서 0.2초의 공격 딜레이를 가지게 하고 매 프레임 체크를 해,

IsAttacking이 true인, 마우스 좌클릭 Pressed 상태일 때 Action을 호출해주는 흐름이다.

 

그렇다면 Action에 구독되어있는 함수는 어떤 것일까?

 

public class TopDownShooting : MonoBehaviour
{
    private TopDownCharacterController _contoller;

    [SerializeField] private Transform projectileSpawnPosition;
    private Vector2 _aimDirection = Vector2.right;

    public GameObject testPrefab;

    private void Awake()
    {
        _contoller = GetComponent<TopDownCharacterController>();
    }

    // Start is called before the first frame update
    void Start()
    {
        _contoller.OnAttackEvent += OnShoot;
        _contoller.OnLookEvent += OnAim;
    }

    private void OnAim(Vector2 newAimDirection)
    {
        _aimDirection = newAimDirection;
    }

    private void OnShoot()
    {
        CreateProjectile();
    }

    private void CreateProjectile()
    {
        Instantiate(testPrefab, projectileSpawnPosition.position,Quaternion.identity);
    }
}

 

공격을 하기 위한 TopDownShooting 스크립트이다.

 

투사체가 나갈 위치인 projectileSpawnPosition 과 발사 방향인 _aimDirection, 실제 투사체 testPrefab이 있다.

 

OnLookEvent에 OnAim을 등록해 활이 돌아가는 것처럼 실제로 발사될 방향도 _aimDirection에 담아준다.

 

TopDownCharacterController 스크립트에서 봤던 것처럼, 좌클릭중 + 딜레이오버 됐을 때 Action을 호출해주고

그 호출되는 함수인 OnShoot 메서드는 프리팹을 생성해주고 있다.