3D Quarter View Action 게임 개발 1일차

mingu Lee·2025년 4월 17일

오늘부터 골드메탈님의 영상을 참고하여 3D 쿼터뷰 액션 게임을 만들어보기 시작했다.

https://www.youtube.com/watch?v=WkMM7Uu2AoA&list=PLO-mt5Iu5TeYkrBzWKuTCl6IUm_bA6BKy

저번에 간단하게 공을 조작하는 3D 게임을 제작해본 적은 있었지만 이번 강의처럼 본격적으로 3D 게임을 만들어보는 것은 처음이라 엄청 기대됐다.

이번에도 골드메탈님이 제공해주신 Asset을 사용했고, 2D에서 Object나 Animation을 만드는 것에 비해 3D는 모델링이나 Animation이 훨씬 복잡하기 때문인지 Asset에 각종 Object의 Prefab과 Animation이 모두 주어졌다.

간단한 Run Animation인데 보기만해도 벌써 어지러운 듯한 느낌이 든다.

이런 Asset을 제공해주신 골드메탈님.. 정말 감사합니다 :)

오늘은 첫 날이라 간단하게 Map과 Player의 이동, 점프, 회피 등 제어에 대한 작업을 진행했다.

  1. Map 제작
  2. Player 생성 및 애니메이션 설정
  3. Player 제어 함수

사실 그 다음 강의인 Item 생성과 무기 시스템까지 진행하려고 했는데 Player 움직임 관련하여 내가 마음에 드는 방향으로 수정하다보니까 시간이 엄청 오래 걸려서 위 2가지만 진행했다.

Map 제작


먼저 Map은 3D Object에서 Cube를 생성하여 바닥과 벽을 만들어주었다.

현재 상황에서는 Player가 바라보는 방향이 고정되어 있기 때문에 맨 아래로 움직여 벽에 닿았을 경우 벽이 Player를 가리지 않기 위해 아래에 있는 벽은 Mesh Renderer를 꺼놨다.

이후 바닥과 벽 4개에 Collider 및 Rigidbody를 추가해주고 마무리하였다.

추가로 Map 자체는 움직이면 안 되기 때문에 Static과 Is Kinematic 등 외부 힘을 받지 않게 설정했다.

Player 생성 및 애니메이션 설정


Map을 만들고나서 Player를 만들었다.

Asset에 Player Prefab이 존재하기 때문에 그대로 사용하였다.

일단, Asset에서 제공하는 Animation이 다양한데 오늘 작업한 Player 모션은 총 4가지이며 다음과 같다.

  1. 걷기
  2. 뛰기
  3. 점프
  4. 회피(구르기)

위 4가지 Animation이 부드럽게 전환될 수 있도록 Animator를 설정해주었다.

처음 시작하면 Idle 상태로 시작하게 했다.

Idle, Walk, Run은 서로 연결되어 있고, 특정 Parameter가 바뀌면 상태가 전환된다.

예를 들어, Idle에서 Player가 키를 눌러 움직이면 Walk 상태로 전환되고, Walk 상태에서 Left Shift를 누르면 Run 상태로 전환된다.

Jump와 Dodge(회피)는 어떤 상태에서도 키를 누르면 작동해야하므로 Any State에 연결시켰다.

또한 Jump는 점프하고 나서 바닥에 닿을 때 Land Animation이 재생된 후 끝나게 설정했다.

사진 왼쪽에는 각 상태로 전환될 때 사용할 파라미터들이다.

Player 제어 함수


Animator를 작성하고 나서 본격적으로 Player를 제어할 함수를 작성했다.

강의에서는 GetAxis로 입력을 받아 구현했지만, 나는 이전에 새로 배운 Player Input을 사용해서 구현했다.

첫 번째로, Walk이다.

Player Input을 추가하고 Action을 새로 만들면 기본적으로 Move Action이 만들어져 있다.

이미 방향키와 WASD 키가 Binding 되어 있으므로 이를 사용했다.

움직임을 처리할 OnMove 함수를 작성했고, 입력으로 들어온 Vector2 값을 읽어서 방향 벡터를 설정했다.

이때, Player의 시선 또한 움직이는 방향을 바라봐야하므로 LookAt이라는 함수를 사용하여 Object를 회전시켰다.

두 번째로, Run이다.

Walk 상태에서 Left Shift를 누르면 뛰기, 떼면 다시 Walk 상태로 돌아가게 했다.

Player Action에 Run Action을 추가했고, 특정 입력 값이 아닌 Button의 클릭 유무를 확인해야하므로 Action Type은 Button으로 했다.

이후 Left Shift 키를 Binding하고 Interaction을 설정했다.

위 사진에 보면 현재 Interaction이 hold로 되어 있는데, 처음에는 Press로 설정했다가 나중에 Dodge를 구현하면서 Hold로 변경했다.

왜냐하면 내가 해왔던 게임들을 떠올려봤을 때, Left Shift 하나만으로 뛰기와 회피를 모두 처리한 게임들이 많았기 때문이다.

Left Shift를 짧게 딸깍 누르고 떼면 구르기, 꾹 누르고 있으면 뛰는 방식이다.

위 방식처럼 구현하고 싶어서 Run의 Interaction을 일정시간 동안 Hold하고 있어야 Run 상태로 전환되도록 했다.

이때문에 단순히 Button을 눌렀냐 아니냐를 확인하는게 아니라 Hold가 수행되었는지, 누르다가 키를 뗐는지를 확인해야했는데, InputValue는 isPressed라는 눌렸는지 아닌지를 확인하는 상태만 존재해서 다른 방법을 찾아야했다.

따로 찾아보니InputAction.CallbackContext라는 파라미터를 받아오면 Interaction이 수행되었다는 performed라는 상태가 존재하는 것을 알게 되었다.

이를 사용하여 키가 Hold 됐으면 Run, 누르다가 뗐으면 다시 Walk 상태로 돌아가게 했다.

참고로 InputAction.CallbackContext를 사용하려면 Player Input의 Behavior 값을 Invoke Unity Events로 바꿔야한다.

세 번째로, Jump이다.

Jump도 Action에 추가하여 Space를 Binding 해주었다.

Run과 달리 스페이스를 누르기만 하면 Jump가 되어야하므로 Interaction으로 Press를 설정했다.

스페이스 바를 누르면 AddForce 함수를 사용하여 위쪽 방향으로 힘을 주었다.

이때, Jump Trigger를 발동시키고 바닥과 다시 충돌했을 때 isJump 값을 false로 하여 착지 모션으로 전환되게 했다.

이렇게 Jump가 잘 마무리된 줄 알았으나.. 테스트하다가 한 가지 문제점을 발견했다.

그냥 바닥에서 Jump를 하면 잘 되는데, 점프를 하면서 벽에 부딪치면 Player가 벽에 달라붙는? 현상이 발생하는 것이었다.

이게 도대체 왜 그런가 싶어서 Collider도 바꿔보고 이것저것 테스트해봤지만 계속 못 찾고 있었는데 다행스럽게도 강의 영상에서 골드메탈님이 해결책을 알려주셨다.

바로 벽으로 만들었던 Object의 재질 때문이었다.

검색해본 결과, Collider를 추가하면 내부적으로 기본 물리 재질을 사용하는데 여기에 마찰력이 존재한다고 한다.

그래서 Physic Material을 새로 생성하여 마찰력을 제거한 후, 벽 Object의 Material에 적용시켜주었다.

새로운 Physic Material을 적용하기 전과 달리 벽이 매끄러워진 것을 볼 수 있다.

네 번째로, Dodge이다.

위 3가지 모션을 구현하는건 나름 할만했는데 이 Dodge를 구현하는 것이 굉장히 힘들었다.

회피 동작은 Left Shift를 그냥 눌렀을 때 발동하면 안 되고, 짧게 눌렀다 뗐을 때 발동하도록 하기 위해서 Interaction으로 Tap을 추가했다.

위 사진처럼 0.3이라는 값 안에 Left Shift를 눌렀다 떼어야만 Interaction이 performed 되었다고 인식하여 Dodge가 발동된다.

특정 방향으로 Dodge를 했을 경우 도중에 방향 전환 및 점프, 다시 Dodge를 할 수 없게 isDodge라는 상태 변수를 추가하여 Dodge 중이면 return 되는 코드를 각 함수에 추가해주었다.

하지만 위 사진과 같이 return 했더니 문제가 발생했다.

Dodge가 끝났을 때 특정 방향으로 이동하려고 방향키를 미리 누르고 있으면 return에 의해 Vector 값이 적용이 안 되어 Dodge 후에 Dodge한 방향으로 계속 움직이는 것이다.

즉, Dodge가 완전히 끝났을 때 방향키를 눌러야만 해당 방향으로 움직인다.

그렇다고 moveVec을 변경하는 코드를 return문 위로 올려버리면 또 문제가 발생한다.

Player의 움직임 자체는 FixedUpdate에서 처리하고 있기 때문에, Dodge 도중 moveVec 값을 변경시키면 Dodge하면서 다른 방향으로 움직일 수 있게 된다.

어떻게 구현할까 고민하다가 Dodge가 끝나는 타이밍에 입력으로 미리 들어온 방향 벡터를 바로 moveVec으로 설정해주는 방식으로 구현했다.

위 사진처럼 EndDodge라는 함수를 만들어서 Dodge Animation 끝부분 프레임에 EndDodge 함수를 Event로 추가했다.

이러한 방식으로 Dodge를 구현하여 Dodge 도중 방향키 입력이 들어와도 Dodge가 끝났을 때 바로 적용되도록 했고, 이로 인해 기존의 딱딱한 Player 제어를 더욱 부드럽게 제어할 수 있도록 했다.

영상으로는 모르겠지만 Left Shift를 Hold하면 Run, 짧게 Tab하면 Dodge가 발동하고 있다.

오늘의 결과물


Walk, Run, Jump, Dodge가 Player의 제어에 따라 부드럽게 전환되면서 움직이는 것을 볼 수 있다.

profile
Github: https://github.com/dlalsrn

0개의 댓글