~2026.02.28 (토)
매일 글을 쓴다고 해놓고 거의 글을 안 썼다. 글을 쓴다고 마음먹는 것부터 쉽지 않게 느껴지지만 그래도 열심히 써야겠지..
2월 9일 이후로 약 2 ~ 3주간 고민한 내용은 애니메이션이었다. 어떤 종류의 애니메이션이든 게임 개발에선 빼놓을 수 없기에 애니메이션의 구현을 잘 정립하는 것은 아주 중요했다.
친구에게 들어보니 Unity에서 애니메이션을 자체적으로 지원한다고 한다. 하지만, 그 시스템은 턴제에는 적합하지 않다고도 말해주었다. 우리는 액션을 처리하면 액션에 달려있는 애니메이션을 재생하는 방식으로 게임을 굴러가게 하고 싶었다. 액션을 처리하면 새로운 액션이 생성되고, 그 액션의 애니메이션도 정해진 순서와 시점에 따라 재생하는 방식으로.
액션 시스템
액션 시스템을 가볍게 예시와 함께 설명하면 이렇다. 플레이어가 스킬을 사용하면 코드는 SpellCastAction이라는 액션을 받아 처리한다. SpellCastAction을 처리하면, AttackDamageAction과 StatusEffectAction 등의 파생 액션이 생겨난다. 이 파생 액션들도 각각의 애니메이션을 갖고 있다.
이런 방식을 택한 이유는 우리가 레퍼런스로 삼은 게임인 Slay the Spire가 이러한 방식을 채택하고 있고, 우리 게임도 비슷하게 굴러가기 때문이다. 만약 플레이어가 아이템, 유물 등의 부가 효과를 주는 물건들을 보유하고 있다면 더 많은 파생 액션들이 생성된다.
그러나 각각의 액션에 대한 애니메이션을 처리하는 것은 조금 어려울 수 있다. 몇몇 애니메이션은 다른 애니메이션과 동시에 실행하고 싶고, 몇몇 애니메이션은 다른 애니메이션과 순차적으로 실행하고 싶다. 다음 예시를 생각해보자.
[스킬을 시전해서, 상대에게 피해를 8 주고 유물 효과로 피해를 3 더 주는 상황]
여기엔 다음과 같은 애니메이션이 들어간다.
[스킬 시전 동작 애니메이션]
[피해를 8 주는 애니메이션]
[유물을 강조하는 애니메이션]
[피해를 3 주는 애니메이션]
이 애니메이션들을 단순하게 순차적/병렬적으로 실행하면 이상하게 보일 수 있다. 최소한 3번째, 4번째 애니메이션은 동시에 실행하고 싶다. 유물 효과로 피해를 입히는 것이므로 유물을 강조하는 효과와 피해가 3 들어가는 효과를 동시에 실행하면 자연스럽기 때문이다.
또한, 스킬 시전 동작이 전부 끝난 후에야 피해가 들어가거나 유물이 강조되는 것은 어색할 수 있다. 만약 스킬 시전 동작이 [스킬 쓰러 상대에게 이동, 상대에게 검 내려침, 다시 자기 자리로 돌아옴]의 3가지의 동작으로 나뉘어 있다면 어떻겠는가? 이 3가지가 전부 끝난 다음에 피해를 8 주는 애니메이션이 재생된다면 어색할 것이다.
따라서, 애니메이션을 여러 파트로 나눠 생각해보기로 했다.
애니메이션의 분리
1. DAG로 접근
모든 애니메이션은 여러 파트로 쪼개 생각할 수 있다. 아까 언급했던 [스킬 시전 동작 애니메이션] 같은 경우,
[스킬 쓰러 상대에게 이동 | 상대에게 검 내려침 | 다시 자기 자리로 돌아옴] 의 3가지 동작으로 나눌 수 있다. 애니메이션을 이렇게 나눌 수 있다면, 다음 애니메이션을 언제 실행할지 정할 수 있을 것이다.
[피해를 8 주는 애니메이션] 은 [상대에게 검 내려침] 파트를 실행할 때 혹은 완료됐을 때 실행하면 좋을 것이다. 이건 그래프로 모델링할 수 있겠다는 생각이 들었다. 다음과 같은 간선을 갖는 그래프를 생각해보자.
[상대에게 검 내려침] -> [피해를 8 주는 애니메이션]
[피해를 8 주는 애니메이션] -> [유물 강조 효과]
[피해를 8 주는 애니메이션] -> [피해를 3 주는 애니메이션]
이건 유향 비순환 그래프(Directed Acyclic Graph)로 표현할 수 있다. 선행되는 애니메이션 파트들이 모두 실행되었다면 이 애니메이션 파트를 실행할 수 있는 방식이다.
이론적으로 완벽하지만 이 방식은 아주 큰 문제가 있었는데, DAG를 해석하고 실행하는 것은 쉬워도 구성하는 것은 아주아주 어렵다는 점이었다.
애니메이션을 연결하려면 다른 애니메이션의 Reference를 쉽게 접근할 수 있도록 해야했고, 어떤 애니메이션들을 Parent-Child 관계로 연결해야할지 찾는 것이 정말 막막했다. 액션이 나오는 패턴이 정해져 있다면 모를까, 유물이나 장비 및 아이템 등 여러 요소들로 인해 액션이 추가되면 Parent-Child 관계를 연결하는 것은 너무나도 복잡해진다.
2. 트리로 접근
DAG를 구성하는 것이 어려워서, 더 쉬운 구조를 생각해보기로 했다. 그것은 바로 트리였다.
우리 시스템의 액션은 액션(1, 2)을 하나(1) 처리하면, 그 액션(1)의 파생 액션(1a, 1b)이 생성되어 계속 처리되는 구조였다. 1a, 1b를 모두 처리하기 전까지 2를 처리하지 않는 구조이다. 이건 트리 구조와 완전히 같기 때문에, 액션 트리로부터 애니메이션 트리를 만들어내면 어떨까 하는 생각이 들었다.
액션을 생성하고 처리하면, 애니메이션 트리도 생성된다. 액션과 애니메이션을 1:1로 대응시키면 Model-side 코드가 View-side 코드의 규칙을 알고 있을 필요도 없이, 액션 트리와 동일한 구조로 애니메이션 트리를 만들어 실행시키면 된다.
트리를 만들었다면 트리를 순회할 규칙을 정해야 한다. 규칙은 간단하게 Preorder (루트 - 왼쪽 - 오른쪽) 로 했고, 각 노드가 애니메이션의 한 파트에 대응하게 만들었다. Pseudo-code로 쓰면 다음과 같다.
public async Task Preorder()
{
var handle = this.Animation();
foreach (var child in this.Children) {
await child.Preorder();
}
await handle;
}
이를 생각해내는 것은 꽤 오래 걸렸지만 결과물은 꽤나 마음에 들었다.
'Unity, 게임 개발' 카테고리의 다른 글
| 2026.05.13 (수) - 유물과 전투 연결 구현 (0) | 2026.05.14 |
|---|---|
| 2026.05.06 (수) - 상태 이상 시스템 구현 (0) | 2026.05.07 |
| 2026.02.09 (월) (0) | 2026.02.10 |
| 2026.02.02 (월) (1) | 2026.02.03 |