여태 깨작꺠작 공부만하고 무언가를 만들어 본 적은 없는 초보입니다. 마음먹고 이번에 시작해보려다 이왕 하는거 고수님들께 조언도 구하고 나태해져 포기하는 일이 없도록 일지라도 남겨보려고 합니다. 



기획부터 간단히 설명해보겠습니다.
플레이어는 4명의 아군을 선택하고 런을 시작합니다. 런 동안 플레이어는 랜덤하게 배정된 전투 스테이지를 클리어하고 아군을 여러 방식으로 강화할 수 있는 이벤트 스테이지에서 정비 후 다시 전투 스테이지로 넘어가는 구조를 반복하게 됩니다. 몇 차례 반복되다보면 다음 챕터(테마)로 넘어가며 더욱 강한 몬스터들을 마주하게 됩니다. 마지막엔 최종 보스 스테이지를 클리어 해 런을 마치는 간단한 게임 구조입니다.
우선 저는 전투 스테이지의 시스템과 유닛, 스킬의 구조 설계에 집중했습니다.좋다면 좋고 안좋다면 안좋은 부분인데 저같은 경우엔 설계에 시간을 좀 과하게 쓰는 편입니다. 아직 일어나지도 않은 리팩토링을 많이 두려워하는 성격이라 처음부터 완결하게 가고 싶다는 마음이 강한 것 같습니다..
전투에서 핵심으로 굴러갈 Ability입니다.


24b0d121e09c28a8699fe8b115ef046f5b49989f


플레이어는 자신의 턴 동안 1개의 행동을 할 수 있습니다. 행동은 카드 시전, 캐릭터 이동, 아이템 사용 3가지로 나뉩니다.

이 행동들을 하기 위해선

1. 무슨 행동을 할 지 선택해야 하고

2. 행동에 대해 대상을 지정해야 하고

3. 이후 행동을 처리합니다.

이 3단계의 처리가 항상 이루어집니다.


예시로 캐릭터 이동의 경우

1. 이동을 위해 캐릭터(타일)을 선택하고

2. 이동을 하기 위한 목적지 타일을 지정해야 하고

3. 이후 캐릭터를 이동시키는 로직이 실행됩니다.


이처럼 굴러가고 이는 카드 시전, 아이템 사용도 동일한 흐름입니다.


그러므로 이 3가지의 행동을 Ability라는 인터페이스로 묶어서,

임의의 행동에 대해 유효한 대상을 선택했는지 확인하기 위해선 IsValidTarget 함수를 호출하면 되고

임의의 행동을 실행하기 위해선 UseAbility 함수를 호출하면 되도록 설계했습니다.



24b0d121e09c28a8699fe8b115ef046c66f52b4f

Battle 매니저 스크립트의 필드입니다.

시전할 행동은 selectedAbility에 할당하고

그 행동의 대상은 currentTarget에 할당합니다.


처음엔 코드를 깔끔하게 관리하는 것에 나름 집중했었는데 수년간 나름대로 코드를 끄적인 경험으로는 완성이 1순위라고 깨닫고는 일단은 매니저 스크립트에 기능 함수들 다 때려박고 각 객체들이 매니저를 참조해서 필요한 함수를 호출하는 전형적인 뉴비 코드가 되었습니다,, 이해부탁드려요.



24b0d121e09c28a8699fe8b115ef0464d58eebca

Tile, Card, Item 이 3개의 행동을 담당하는 UI들은 마우스 입력을 받아, Battle 매니저의 SelectAbility 함수를 호출하며 각각 자기 자신을 인자로 넘깁니다.

이후 selectedAbility가 비어있으면 새로 할당하고 비어있지 않으면 이 행동이 selectedAbility의 대상이 됩니다.


예로 '카드 1장을 선택해 해당 카드를 복사합니다' 라는 능력의 카드 A가 있습니다.

플레이어는 A 카드를 누르면 SelectedAbility엔 A가 담기고 이후 선택하는 임의의 카드는 currentTarget이 되어 A 카드의 능력이 실행되는 구조입니다.

만약 A 카드의 대상이 유효한 대상인지 확인하기 위해선 앞서 Ability 인터페이스에서 정의했던 IsValidTarget 함수를 재정의를 해 호출하여 사용합니다.


24b0d121e09c28a8699fe8b115ef0464d18fe7c1

selectedAbility의 스킬 로직을 호출합니다. 이후 실행한 행동이 만약 '카드 시전'이었을 경우엔 해당 카드를 버려진 카드덱(묘지)로 보내는 처리까지 실행합니다.

이후 플레이어는 1개의 행동을 했으므로 적의 턴으로 넘어갑니다. (이건 테스트 환경을 위해 온오프 토글 형식으로 할까 고민중입니다.)


이렇게 구현한 덕분에 Ability만 상속받으면 원하는 새로운 카드 스킬들을 쉽게 추가할 수 있게 됩니다.



이제 3가지의 행동이 실제로 어떻게 굴러가는지 보겠습니다. 우선 캐릭터 이동입니다.


24b0d121e09c28a8699fe8b115ef046b6d679936

캐릭터 이동 Ability는 TileUI 스크립트에 그냥 상속시켜 사용했습니다. 원래라면 TileUI와는 별개로 MoveAbility : Ability 이런 식으로 관리하는 것이 옳은 구조긴 합니다만

TileUI가 워낙 하는 일이 없기도 하고 캐릭터 이동은 그나마 대충해도 어떻게든 굴러가기에 그냥 TileUI에 구현하기로 했습니다.


유효한 대상인지 반환하는 IsValidTarget에서는 target이 타일이어야 true를 반환해 행동을 실행시키도록 합니다.

당연하게도 캐릭터 이동이니 타일A클릭한 후 타일 B를 클릭해야 이동이 될 것입니다.


UseAbility에서는 혹시 몰라 한번더 IsValidTarget을 통해 검사를 하고 유효한 대상일 경우 battle 매니저 스크립트의 Move 함수를 호출하여 캐릭터 이동을 진행합니다. 바로 Move 함수를 보겠습니다.



24b0d121e09c28a8699fe8b115ef046c62f22a4b98

Move 함수와 애니메이션 함수입니다.


이 프로젝트에선 데이터 객체와 UI 객체, 그리고 기능 스크립트 이 3개를 완전히 분리하는데에 집중했습니다.

이유는 예시로 유닛이 대미지를 잘 입는지 테스트를 하기 위해선 그냥 Unit 객체의 health 수치가 잘깎이는지, TakeDamage 함수가 잘 호출되는지만 확인하면 되는데 Unit과 UI가 한 뭉텅이로 되면 테스트를 위해 UI까지 어떻게든 꽂아두든, 예외처리를 하든 해야하는 번거로움이 생겨 UI가 없더라도 혹은 Unit이 없더라도 각각 테스트에서 원활히 작동하게 만들고 싶었습니다. (덕분에 둘이 맵핑시키는 과정이 훨씬 더러워졌습니다만 그래도 만족중입니다.)


이이서 설명하자면 Move에서는 Tile과 맵핑된 Unit 데이터 객체를 Dictionary 상에서 이동시킵니다. 여기까진 게임 화면에선 아무런 변화는 없을 것입니다.

이후 MoveAnimation을 호출해서야 unitUI 객체들을 업데이트된 Tile 좌표로 이동시켜 시각적인 변화를 보여줍니다.

(아직은 position 값만 바꿉니다만 나중에 두트윈을 통해 애니메이션을 줄 생각입니다.)



이런 식으로 이동하게 됩니다. 캐릭터는 게임 쇼군 쇼다운의 캐릭터를 갖고 와서 썼고 나머진 핀터 자료 보면서 직접 작업 했읍니다. 아래 hud 영역엔 카드 핸드 보여줄 예정.


언젠가 쓸 이후 글에서 Move에 Swap 기능도 넣어서 캐릭터가 있는 타일을 선택하더라도 정상적으로 작동하게 만들 생각입니다. 카드도 추가해보고요.당장엔 고작 캐릭터 이동에 과하게 코드를 작성한 감이 없잖아 있지만.. 아이템이나 카드 스킬 추가를 위한 밑작업이라고 생각합니다.



이런 곳에 글을 써보는 게 처음이라.. 똥글 끝까지 읽어주셔서 감사합니다. 다른 분들 보면 코드도 깔끔하게 올리시고 플레이도 GIF로 올리시던데 이 부분도 좀 공부해봐야겠습니다.