ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TopDown Shooting Game/캐릭터 이동 기능
    게임 개발기록 2024. 5. 20. 14:53

    캐릭터를 이동 하게 하는 기능을 추가한다. 

     

    캐릭터는 플레이어뿐만이 아니라 몬스터들도 이동을 하기에 둘 다 사용을 할 수 있게 만들어 준다.

    이동은 rigidbody를 이용한 중력에 의해 이동을 하게 해준다. 

     

    input system을 사용 해서 키 입력을 받고 함수를 호출 하게 한다. 

     

    TopDownController 클래스에서 이벤트들을 만들어 주고 PlayerInputController 클래스에서 InputSystem 함수들을 만들어 준다. 

     

    PlayeInputController 에서 InputSystem 함수들을 호출 하게 하고 TopDownMovement 클래스에서 작동이 되게 해준다. 

     

    Vector2의 값을 가져와서 ApplyMove 함수를 FixedUpdate에 실행 하게 해서 캐릭터가 움직이게 한다. 

     

     

    TopDownController 클래스에 이벤트를 추가 시켜준다. 

     

     public event Action<Vector2> OnMoveEvent;
     public event Action<Vector2> OnLookEvent;
     public event Action<AttackSO> OnAttackEvent;

     

    Action을 사용해서 이벤트를 만들어 준다. OnMoveEvent로 움직임을 OnLookEvent로 무기의 각도를 변경을 해줄 것이다. 그래서 Vector2 를 매개변수로 받게 한다. 어택은 좀 다르다.

     

    그리고 이벤트를 호출 하는 함수도 만들어 준다.

     

        public void CallMoveEvent(Vector2 direction)
        {
            OnMoveEvent?.Invoke(direction);
        }

        public void CallLookEvent(Vector2 direction)
        {
            OnLookEvent?.Invoke(direction);
        }

        public void CallAttackEvent(AttackSO attackSO)
        {
            OnAttackEvent?.Invoke(attackSO);
        }

     

    ?. 을 하게 되면 이벤트가 채워져 있는지, null인지를 확인 하고 채워져 있다면 앞에, 아니면 뒤에 것을 작동 하게 한다. 

    지금은 Event에 함수가 있다면 Invoke, 함수를 실행 되게 했다. 

     

    그 다음에 PlayerInputSystem 클래스를 작성 해서 이벤트를 호출 하는 함수를 호출 하게 해준다. 

    그전에 InputSystem을 먼저 만들어 줘야 한다. 

     

    먼저 인풋 액션을 만들어 준다. 마우스 우클릭을 통해 에셋 추가 해주면 된다. 

    되도록 폴더를 따로 만들어 줘서 관리를 해주면 좋다. 

     

    인풋 액션을 만들고 Controll Schemes를 만들어 준다. 

    지금은 키보드와 마우스에 입력을 받을 것이니 KeyboardMouse 라는 이름으로 생성을 해주겠다. 

     

    그 다음에 액션 맵을 만들어 준다. 

    맵은 여러 액션들을 갖고 있는 거라고 생각 하면 되는데 Player라는 액션맵을 만들고 Move, Look, Attack 등과 같은 액션들을 포함 하고 있다고 생각 하면 된다. 

     

    말한대로 Player 액션맵을 추가 하고 Move, Look, Fire 액션들을 추가 해준다. 

    그리고 액션들을 설정 해줘야 한다. 

    액션타입과 컨트롤 타입들을 설정 해줘야 하는데 지금은 Move와 Look은, 액션타입 Value와 컨트롤타입 Vecto2로 설정을 해주겠다. 그리고 Fire는 액션타입 Value와 컨트롤 타입 Any로 해준다. 

     

    그리고 바인딩을 추가 해줘야 한다. +버튼을 눌러서 자동추가 기능도 사용을 하면 편리 하다.

     

    그리고 path 도 설정을 해줘야 한다. Move에는 w,a,s,d를 설정 해주고, Look에는 마우스 포지션을 설정 해준다. 

    그리고 Fire는 왼 쪽 클릭으로 설정. 

    이렇게 하면 wasd를 눌렀을 때, 마우스포지션이 변경 됐을 때, 왼 쪽이 클릭 됐을 때 메세지를 보내게 할 수 있다. 

     

    이렇게 해주고 저장을 해준 다음에 플레이어 오브젝트에 인풋액션을 추가 해주면 된다. 

     

    그리고 이제 PlayerInputController 클래스를 작성 해준다. 

    여기서 InputSystem 을 호출하게 해준다. 아까 만들어 둔 액션들을 함수로 만들어 준다. 

     

    Move 액션을 OnMove 함수로 만들어 주면 w,a,s,d가 눌렸을 때 OnMove 함수 안에 있는 내용이 실행 되게 한다. 약간 추상메서드나 인터페이스 함수들을 재정의 해야 하는 것과 비슷하다고 볼 수 있다. 

     

    그러니 Move와 Look, Fire 함수를 만들어 준다. 

     

        public void OnMove(InputValue value)
        {
            Vector2 moveInput = value.Get<Vector2>().normalized;
            CallMoveEvent(moveInput);
        }

     

    지금은 캐릭터 이동만 정리를 하고 있으니 Move만 적어 준다. 

     

    이렇게 하면 w,a,s,d가 눌렸을 때 Vector2의 값으로 x,y의 값을 받아오게 되고(왼 쪽(-1,0), 오른 쪽(1,0) 등등) 그 값으로 Event를 호출 하게 한다. *여기서 normalized는 정규화인데 Vector2의 값이 1,1이 될 경우 1만큼만 이동을 해야 하는데 2로 이동을 하게 되어서 더 많이, 더 적게 이동을 하게 된다. 그래서 이동 하는 값을 1로 맞춰주는 것을 해줘야 하는데 그것이 정규화이고 normalized를 사용 해서 할 수 있다.

     

    그리고 CallMoveEnvent를 바로 사용 하려면 상속을 받아야 한다. 아니면 객체를 생성 하던가 아니면 클래스.어쩌구 하던가 등등 지금은 TopDownController를 상속 받아서 사용 했다. 

     

    그런데 지금은 Event가 없다. 비었다. Null이다. 그래서 실제로 움직임이 구현 되는 TopDownMovement 클래스를 작성 해주도록 한다. 

     

    여기서는 TopDownController 클래스를 객체로 생성을 해주고 event를 사용하게 해주겠다. 왜인지는 지금은 모름.

    아마 흠

     

    그러니 private TopDownController controller; 변수로 선언을 해주고 Awake 함수에서 GetComponent를 해준다.

     

    그리고 캐릭터의 이동을 rigidbody를 이용해서 구현을 할 것이다. Vector2의 값으로 velocity를 주어서 이동을 하게 한다. 그러니 rigidbody 컴포넌트도 가져와 준다. 

     

    private TopDownController controller;
    private Rigidbody2D movementRigidbody;

     

      private void Awake(){

     controller = GetComponent<TopDownController>();
     movementRigidbody = GetComponent<Rigidbody2D>();

    }

     

    그리고 게임이 실행이 되면 event에 함수를 추가 시켜 준다. 왜? 함수를 실행 하게 하려면, 아니 이벤트에 함수를 넣으려면 함수 안에 함수를 넣거나 아무튼 함수가 작동 되게 해야한다. 그러면 함수를 두 번 써야 하는데 스타트 함수에 사용 하면 그냥 바로 추가 하면 됨. 뭔소리인지 다들 알거라 생각한다. 나보다 똑똑하니까. 이 이유가 아닐 수도 있다. 

    어찌 됐든 이벤트에 함수를 추가 하기 위해서다. 특정 조건에 추가 하려는 것이 아니라 추가 하기 위해서

     

     private void Start()
     {
         controller.OnMoveEvent += Move;
     }

     

    게임이 시작 되면  Move 함수가 event에 추가 되게 해주고 Move 함수를 만들어 준다. 

     

    private void Move(Vector2 direction)
    {
        movementDirection = direction;
    }

     

    이 Move 함수는 event 함수라고 생각을 하면 된다. CallMoveEvent, 그러니까 movementDirection이라는 변수에 wasd 로 입력 받은 Vector2의 값으로 바꿔주는 함수인 것이다. 그러니까 movementDirection 변수도 만들어 준다. 

     

    private Vector2 movementDirection = Vector2.zero;

     

    왜 제로냐? 음 오류가 날 수도 있다고 했었나...ㅎㅎ... 아무튼 0으로 해준다.

    이렇게 하면 wasd가 눌렸을 때 OnMove가 실행 되고 CallMoveEvent를 호출 함으로써 movementDirection 변수의 값을 변경 하게 해준다. 

     

    여기까지만 하면 이동은 안 된다. 이 변수의 값으로 rigidbody에 velocity를 주어서 이동 하게 해주는 코드를 작성 해준다. 

     

      private void ApplyMovement(Vector2 direction)
      {
          direction = direction * characterStatHandler.CurrentStat.speed;
          movementRigidbody.velocity = direction;
      }

     

    이 함수를 만들어 주고 이 함수를 실행 하게 할 때 movementDirection값을 매개변수로 넘겨주게 하면 그 값에(방향에) 스피드만큼 곱해주고 velocity(속도)로 변경을 해주게 해서 이동이 되게 한다. 

     

    이 함수는 FixedUpdate를 사용 해서 계속 호출을 하게 해준다. 

     

     private void FixedUpdate()
     {
         ApplyMovement(movementDirection);
     }

     

    왜 FixedUpdate냐? 물리업데이트 관련은 FixedUpdate라고 한다. 일반 update와 순서도 상관이 있겠지만 그것도 참고하자. 

     

    이렇게 해주면 FixedUpdate 마다 ApplyMovement를 호출 하게 될 것이고, movementDirection은 wasd를 누를 때마다 값이 변경 됨으로써 이동처리가 될 것이다. 여기서 의문점이 들 수도 있는 게 있을 것인데 wasd를 뗄 때도 OnMove 함수가 호출이 된다. 그래서 뗄 때 다시 값이 0,0 의 Vector2의 값이 되어서 캐릭터는 가만히 있게 된다. 

     

    이렇게 코드 작성을 마무리 해주고 Player 오브젝트에 스크립트를 추가 시켜주면 된다. 

     

    PlayerInputController 가 TopDownController를 상속 받았으니 PlayerInputController와 TopDownMovement만 추가 시켜주면 된다. 

     

    이렇게 해주면 InputSystem을 이용한 캐릭터 이동 구현을 할 수 있게 된다. 

Designed by Tistory.