로그인게임하기
구조 읽기

[100턴 구조 읽기 4] 캐릭터 하나, 행동 일곱 가지

2026.10.10

졸업까지 100턴 구조 읽기 · 4편

졸업까지 100턴의 학생은 전투에서는 스스로 싸우고, 직접 조작할 때는 패드를 따르고, 보드에서는 말이 되고, 교실에서는 산책합니다. 이 모든 모습이 같은 캐릭터 클래스입니다. 상태 머신과 행동 객체를 나눠 둔 구조를 보겠습니다.

PROBLEM

상황마다 캐릭터 클래스를 만들 수는 없습니다

같은 학생이 화면에 따라 전혀 다르게 움직여야 합니다. 상황마다 캐릭터를 따로 만들면 능력치, 버프, 스킬, 애니메이션 코드가 모두 복사됩니다.

그래서 캐릭터가 무엇인지와 지금 어떻게 움직이는지를 나눴습니다.

STRUCTURE

세 층 구조

ElStateObject사내 프레임워크의 상태 머신. 대기, 이동, 추적, 공격, 스킬, 사망 같은 상태와 애니메이션을 맡습니다
TDCharacter능력치, 버프, 상태 이상, 스킬, 피해 처리. 캐릭터가 무엇인지를 맡습니다
TDStrategy상태마다 실제로 무엇을 할지. 교체할 수 있는 행동 객체입니다
STATE

상태 머신

상태가 바뀌면 들어가는 처리, 애니메이션 전환, 나오는 처리가 차례로 불립니다. 매 프레임에는 지금 상태로 Do 가 불립니다.

ElStateObject.csTDClient/Assets/ElFramework/Sources/ContentBase/ElStateObject.csr5406 · 138–153줄
public void SetState(ElStateTypes st)
{
    if (currentType == st) return;

    ElStateTypes prevType = currentType;
    currentType = st;

    if (attackDelayRoutine != null)
    {
        StopCoroutine(attackDelayRoutine);
    }

    Entry(prevType, currentType);
    SetAnimation(StateToAnimState(st));
    Exit(prevType, currentType);
}
순서를 확인해 두세요

이 구현은 새 상태의 Entry 를 먼저, 앞 상태의 Exit 를 나중에 부릅니다. 흔히 쓰는 Exit 다음 Entry 와 순서가 반대라서, 새 상태에 들어가는 코드가 앞 상태의 정리가 끝났다고 가정하면 안 됩니다.

STRATEGY

행동은 Strategy 에 맡깁니다

TDCharacter 는 상태 처리를 자신이 들고 있는 Strategy 에 그대로 넘깁니다. 스킬 자동 사용 여부도 Strategy 가 정합니다.

TDCharacter.csTDClient/Assets/Sources/Content/TDCharacter.csr5406 · 501–523줄
protected override void Do(ElStateTypes currentType)
{
    if (warmUpTime > 0f)
        warmUpTime -= Time.deltaTime;
    else
        warmUpTime = 0f;

    strategy.Do(currentType);

    if (strategy.AutoPlaySkill && activeSkill1 != null)
    {
        activeSkill1.CheckCondition(currentType);
    }

    if (strategy.AutoPlaySkill && activeSkill2 != null)
    {
        activeSkill2.CheckCondition(currentType);
    }

    if (strategy.AutoPlaySkill && activeSkill3 != null)
    {
        activeSkill3.CheckCondition(currentType);
    }
Strategy쓰이는 장면
Offensive · Defensive전투 AI. 적을 찾고 따라가 공격합니다
Playable직접 조작. 가상 패드와 길게 눌러 쓰는 스킬
Board보드의 말. 칸 단위로 이동하고 도착을 알립니다
Spline교실과 도서관의 산책 NPC
Hammer대장간 미니게임
Idle가만히 서 있기
SWAP

실행 중에 행동을 갈아 끼웁니다

게임 컨트롤러가 에드윈에게서 로라에게 넘어가고, 자동 전투 보석은 반대로 에드윈에게 돌아가는 그림
조작할 캐릭터를 바꾸면 조작용 Strategy 와 AI Strategy 가 서로 자리를 바꿉니다.

전투 중 조작할 캐릭터를 바꾸면, 새 캐릭터에는 조작용 Strategy 를 씌우고 앞 캐릭터에게는 원래의 AI Strategy 를 돌려줍니다.

World.csTDClient/Assets/Sources/Content/World/World.csr5406 · 248–251줄
lastStrategy = chr?.GetStrategy();

TDStrategy_Playable stg = new TDStrategy_Playable(chr, field);
stg.SetVirtualPad(virtualPad);
World.csTDClient/Assets/Sources/Content/World/World.csr5406 · 159–165줄
if (lastStrategy != null && lastController != null)
{
    var owner = lastController.GetFollowingCharacter();
    owner.SetStrategy(lastStrategy);
    lastStrategy.StopMove();
    owner.SetState(ElStateTypes.WAITING);
}

Strategy 는 만들어지는 순간 스스로 캐릭터에 등록됩니다. 그래서 new 가 곧 교체입니다.

TDStrategy.csTDClient/Assets/Sources/Content/TDStrategy.csr5406 · 22–28줄
public TDStrategy(TDCharacter owner, TDField field)
{
    this.owner = owner;
    this.field = field;

    this.owner.SetStrategy(this);
}
SPLINE

디자이너가 그린 길이 이동 그래프가 됩니다

도서관 바닥에 그린 곡선과 노드를 따라 학생들이 걷고, 로라가 깃펜으로 새 길을 그리는 그림
바닥에 그린 곡선의 양 끝 노드가 이웃 관계가 되어 산책 동선이 됩니다.

산책 NPC 의 길은 코드로 만들지 않습니다. 디자이너가 에디터에서 스플라인을 그리고 양 끝에 노드 번호를 달면, 코드가 그 번호를 읽어 이웃 관계를 만듭니다.

SplineGraph.csTDClient/Assets/Sources/Content/Strategy/SplineGraph.csr5406 · 15–22줄
public SplineGraph(SplineContainer container)
{
    splineContainer = container;
    foreach (var spline in container.Splines)
    {
        if (!spline.TryGetIntData(NodeKey, out var intDatas) || intDatas.Count < 2) continue;

        var nodeIds = intDatas.Select(p => p.Value).ToList();
SplineGraph.csTDClient/Assets/Sources/Content/Strategy/SplineGraph.csr5406 · 40–47줄
    // 노드 연결
    for (var i = 0; i < splineInNodes.Count; i++)
    {
        var node = splineInNodes[i];
        var neighborId = nodeIds.First(p => p != node.Id);
        node.AddNeighbor(neighborId, spline, node.Id != nodeIds[0]);
    }
}

NPC 는 노드에서 잠시 쉬다가 이웃 가운데 하나를 골라 걸어갑니다. 동선을 바꾸고 싶으면 스플라인만 다시 그리면 됩니다.

RETRO

돌아보며

잘된 점

  • 새 행동은 Strategy 클래스를 만들어 추가합니다.
  • 보드의 말, 산책 NPC, 미니게임 캐릭터를 새 캐릭터 클래스 없이 만들었습니다.
  • 조작 전환은 Strategy 를 바꿔 끼우면 끝납니다.

아쉬운 점

  • 기본 공격 로직이 부모 Strategy 에 들어 있어, Board · Spline · Hammer 는 부모의 Do 를 부르지 않는 방식으로 피해 갑니다.
  • TDCharacter 가 1,768줄로, 능력치부터 피해 처리까지 이 클래스가 맡고 있습니다.
  • Entry 와 Exit 의 순서가 일반적인 상태 머신과 반대입니다.

정리

  1. 무엇인지와 어떻게 움직이는지를 나눕니다. 캐릭터는 하나, 행동은 갈아 끼웁니다.
  2. 상태는 프레임워크, 행동은 게임. 상태 머신은 사내 프레임워크가, 상태별 행동은 게임 코드가 맡습니다.
  3. 데이터로 그린 길. 동선은 코드가 아니라 디자이너가 그린 스플라인입니다.

다음 편에서는 같은 프로젝트를 앱, PC, 웹, 게임 포털, 토스 미니앱으로 나눠 출시한 방법을 보겠습니다.

← 개발 노트 목록