0. 들어가기에 앞서
화요일부터 개인 프로젝트가 시작되고, 5일간 진행될 예정이다. 혼자서 진행해야 하는 프로젝트인 만큼 준비를 미리 해 보고자 한다.
게임 기획서 - 횡스크롤 액션 + 슈팅 게임
// 아이템 기획은 기본적으로 매트로배니아류 게임과 같은 구성을 해 보고자 한다.
// 따라서 포션은 따로 없고 아티펙트 정도 느낌의 아이템만 구현한다.
// 체력 회복에 관해서는, 몬스터 처치 시 일정 확률로 체력 회복이 가능한 알갱이들이 떨어지는 방식.
이번 프로젝트에서 무엇보다도 에셋의 존재 여부가 중요했다.
근거리 공격과 원거리 공격이 전부 존재하는 2D 캐릭터 스프라이트 에셋의 존재여부가 매우 중요했으며, 사실 이런 에셋을 못 구하면 아예 프로젝트 기획 자체를 엎고 3D TPS 게임을 만들 작정이었다.
하지만 여러 곳을 뒤져본 끝에 내가 생각했던 디자인과는 조금 달라도, 근거리 공격과 원거리 공격 에셋이 전부 존재하는 캐릭터 에셋을 발견했다.
itch.io에서의 무료 캐릭터 스프라이트를 사용하기로 했고, 사용할 디자인은 아래와 같다.
https://dreamir.itch.io/characters-pack
(원래 원했던 에셋은 검 + 총 느낌의 캐릭터였지만... 일단 원거리 마법 쓰는 캐릭터라도 감지덕지 써야겠다)
이 에셋에서의 캐릭터 디자인을 뜯어보면 일단 내 프로젝트에 필요한 모션은 다 있었다.
근거리 공격 모션이 다양하게 있었고 원거리 공격 모션과 원거리 공격 도트까지 따로 찍혀 있었다.
일단 제일 중요한 캐릭터 에셋은 이걸로 결정해도 될 것 같았다.
그러면 이제 캐릭터 에셋으로 움직임을 한 번 살펴볼 때이다. 저번 프로젝트 때는 팀장님이 InputSystem으로 조작키를 변경하는 것까지 넣었었으나, 그 단계까지 할 수 있을지는 조금 고민해보기로 하고 우선은 InputSystem 자체의 사용에만 초점을 맞춰보았다.
게임패드 지원 기능은 넣을 수 있으면 재밌을 것 같다. 이 부분은 당장 작업하기에는 아직 작업물이 없어서 일단은 체크 해제해두고, 키보드와 마우스 조작 위주로 작업해보자.
횡스크롤 액션 게임인데다 점프 키는 따로 만들거라, 상하 조작키가 당장 쓰일 일이 없긴 하다. 하지만 혹시 나중에 사다리 기능이 추가될 수 있다는 가정 하에 상하 키는 지우지는 않았다.
직접 다시 해 보려니까 헷갈렸던 것.
코드로 InputSystem에 반영된 키를 사용했는데 왜 안 먹히나 했더니, 플레이어에 InputSystem을 넣지 않은 것이 원인이었다.
위와 같이 세팅하고 코드를 아래와 같이 약식으로 짰다.
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
public Vector2 InputDirection { get; private set; }
private Rigidbody2D _rigid;
private Animator _animator;
private bool _isMove;
private SpriteRenderer _spriteRenderer;
private CapsuleCollider2D _capsuleCollider2D;
[SerializeField] private float _moveSpeed;
private void Awake()
{
_rigid = GetComponent<Rigidbody2D>();
_animator = GetComponent<Animator>();
_spriteRenderer = GetComponent<SpriteRenderer>();
_capsuleCollider2D = GetComponent<CapsuleCollider2D>();
}
private void FixedUpdate()
{
SetMove(_moveSpeed);
}
public void OnMove(InputValue value)
{
InputDirection = value.Get<Vector2>();
}
private void SetMove(float moveSpeed)
{
Vector2 moveDirection = (transform.right * InputDirection.x).normalized;
if(moveDirection.x == 0)
{
_isMove = false;
}
else
{
_rigid.velocity = moveDirection * moveSpeed;
_isMove = true;
_spriteRenderer.flipX = moveDirection.x < 0;
_capsuleCollider2D.offset = moveDirection.x < 0? new Vector2(-0.4f, 0.8f) : new Vector2(0.4f, 0.8f);
}
_animator.SetBool("IsMove", _isMove);
}
}
이게 최종적으로 나온 코드였지만 처음엔 이런 문제를 겪었다.
플레이어의 충돌체는 캡슐2D로 만들었으며, 위와 같이 검이 있는 부분까지 통째로 하기 보단 몸체가 있는 부분만 충돌체 설정하는 것이 자연스러워 보였다. 하지만 이렇게 설정하니 캐릭터 조작에서 문제가 생겼다.
캐릭터가 비대칭이다 보니 왼쪽을 바라보면 충돌체의 위치가 부자연스러워지는 문제가 생긴 것이다.
처음에 이 문제를 해결하기 위해서 생각한 방법은, 아예 캐릭터 자체를 Rotate해 버리는 방법이었다.
이미 배우고 있는 2D 미니 프로젝트에서 Rotate로 플레이어를 움직이고 있으니 이번에도 이렇게 하면 문제가 없겠지 싶었다.
하지만 InputSystem을 사용하고 있다 보니 아주 다른 출력이 발생했다.
오른쪽으로 가는 것은 문제가 없지만, 왼쪽으로 가려고 꾹 누른 순간 계속 좌우로 바뀌면서 그 자리에 고정되어 버렸다. 이 문제를 발견하자 마자 캐릭터 방향 자체를 돌리다 보니 왼쪽으로 돌리는 것 자체가 오른쪽으로 돌리는 것으로 작용한다는 사실을 알게 되었다.
그렇다면 Rotate을 쓰는 방식은 불가능하니 결국 애니메이션 자체는 Flip으로 뒤집을 수밖에 없다. 일단은 애니메이션을 돌리는 건 그렇다 쳐도 충돌체는 어떻게 해야 할까?
충돌체의 좌표를 옮기는 것은 시도해본 적이 없어서 이것저것 건드려 보다가, 아래와 같은 옵션에 집중하게 되었다,
이때까지 모양을 직접 조작하기 바빴는데, 이게 충돌체의 좌표와 비슷한 역할을 한게 된다는 사실을 알게 되었다. 또한, 이걸 잘만 이용하면 충돌체의 좌표를 이동시킬 수 있다는 것도 알게 되었다.
(0.4, 0.8)일 때 오른쪽 좌표와 일치하고
(-0.4, 0.8)일 때 왼쪽 좌표에 알맞게 들어가는 것을 확인할 수 있었다.
그래서 Capsule Collider를 직접 이동하는 방식으로 구현해 보는 것으로 시도하기로 했다.
그 부분이 위 코드에서 적은 이 부분이다.
_capsuleCollider2D.offset = moveDirection.x < 0? new Vector2(-0.4f, 0.8f) : new Vector2(0.4f, 0.8f);
여기서 또 특징을 하나 안 게, X축과 Y축으로 되어 있어서 Transform인줄 알았는데, Offset은 벡터 좌표라는 사실이다.
이와 같이 반영하여 여기까지 움직임을 구현하였다.
충돌체도 의도한 대로 이동하는 것을 확인할 수 있었다.