Project/PaintWar

[Unity] 무기마다 다른 범위를 데이터와 패턴으로 분리하기

유탐기 2026. 8. 29. 19:49
반응형

Paint War의 공격 스킬은 직선, 십자, 사각형 등 타일을 칠하는 형태가 서로 다릅니다. 무기가 추가될 때마다 공격 범위를 계산하는 조건문을 늘리기보다는, 무기 데이터와 범위 계산을 분리하는 방식으로 구성했습니다.

1. 무기 데이터와 범위 계산은 역할이 다릅니다

무기마다 쿨타임, 사거리, 공격 지연, 이펙트와 같은 설정이 다릅니다. 이 값들은 WeaponData라는 ScriptableObject로 관리했습니다. 반면 실제로 영향을 받을 타일 좌표를 계산하는 일은 별도 패턴 클래스가 담당합니다.

public interface IWeaponPattern
{
    IEnumerable<Vector2Int> GetOffsets(
        WeaponData weapon, Vector3 forward);
}

여기서 Offset은 플레이어가 있는 타일을 (0, 0)으로 보았을 때의 상대 좌표입니다. 이를 이용하면 무기별 범위 계산이 맵의 절대 좌표를 직접 알 필요가 없습니다.

2. 패턴 종류를 선택하는 Resolver

WeaponPatternResolver에서는 WeaponPatternType과 실제 패턴 구현을 연결합니다. 십자 패턴은 CrossPattern, 가로·세로 범위는 SquarePattern, 전방 공격은 ForwardLinePattern 또는 ForwardConePattern 등으로 분리되어 있습니다.

private static readonly Dictionary<WeaponPatternType, IWeaponPattern> Patterns
    = new()
{
    { WeaponPatternType.Bomb3x3, new SquarePattern(1) },
    { WeaponPatternType.ForwardLine, new ForwardLinePattern() },
    { WeaponPatternType.Cross, new CrossPattern(true) },
    { WeaponPatternType.Square5x5, new SquarePattern(2) }
};

실제 저장소에는 위 코드 외에도 다른 패턴이 등록되어 있습니다. 무기의 종류를 판단하는 로직과 개별 타일 배치 로직을 분리했으므로, 기존 계산 코드를 길게 수정하지 않고 새 패턴 구현을 추가할 수 있습니다.

3. 문자열 배열로 공격 범위를 표현하기

정해진 도형만으로 표현하기 어려운 공격은 GridPattern을 사용했습니다. WeaponData의 patternRows와 patternPivot을 읽고, 각 칸의 문자를 검사해 타일 오프셋을 생성합니다.

int localX = column - pivot.x;
int localY = pivot.y - row;
yield return r * localX + f * localY;

f는 전방, r은 오른쪽 방향을 뜻합니다. 즉 데이터에는 플레이어 기준 도형을 저장하고, 실행할 때 캐릭터가 바라보는 방향으로 회전한 타일 좌표를 얻습니다. 또한 레벨 3과 5에 별도 패턴을 저장할 수 있어 스킬 강화도 데이터로 처리할 수 있습니다.

4. 화면 표시와 실제 적용이 달라지지 않도록

범위가 계산되더라도 반드시 타일을 칠할 수 있는 것은 아닙니다. WeaponPatternImpactResolver에서는 WeaponPatternTraversal.CanReachOffset()으로 유효한 타일을 모은 뒤, 장애물 파괴·폭탄 기폭·타일 점령을 순서대로 처리합니다.

여기서 중요한 점은 시각적인 범위와 실제 서버 판정이 같은 패턴 계산을 참조한다는 것입니다. 한쪽은 십자 5칸으로 표시하는데 실제 적용은 다른 위치를 칠한다면 사용자가 결과를 이해하기 어렵기 때문입니다.


정리

WeaponData는 무기가 무엇인지, IWeaponPattern은 어떤 타일에 영향을 주는지, WeaponPatternImpactResolver는 그 타일에 어떤 결과를 적용하는지를 담당합니다. 무기를 스킬과 같은 구조로 다루면서 범위와 효과를 확장할 수 있도록 구분했습니다.


참고한 구현 코드

반응형