UNITY 6 · C# · 3인 팀 개발

AI 로봇 키우기 Technical Portfolio

3인 팀으로 만든 방치형 RPG 모바일 게임.
코어 아키텍처와 전투·스킬 시스템, 데이터 파이프라인, 에디터 툴을 맡았습니다.

개발 기간 2025.12 ~ 2026.03
팀 구성 프로그래머 2 · 기획/아트 1
엔진 Unity 6000.0.60f1
상태 ● 완료
GitHub
rladbals0129@naver.com
AI 로봇 키우기 시연 영상 썸네일
시연 영상
SCROLL
다이어그램

클래스 다이어그램

클래스를 클릭하여 상세 코드를 확인하세요

담당 역할

담당 역할 개요

프로젝트에서 맡은 핵심 시스템을 소개합니다.

코어 아키텍처

ServiceLocator 패턴 기반의 서비스 지향 아키텍처 설계. GameManager, EventBus, ResourceManager 등 프레임워크 레벨 인프라 구축.

ServiceLocator.cs GameManager.cs EventBus.cs MonoSingleton.cs ObjectPool.cs ResourceManager.cs

전투 시스템

스테이지·웨이브 진행, 자동/터치 공격, 데미지 계산, 몬스터 스폰 패턴, 다중 타겟 전투 등 전투 흐름 전체를 설계·구현.

CombatService.cs CombatRunner.cs MonsterSpawner.cs CombatSettings.cs SpawnPattern.cs UnitView.cs

스킬 시스템

그리드 기반 스킬 트리(인접 노드 해금), 연구 타이머 시스템, 패시브 스탯 보정, 특수 효과(SkillSpecialType) 등 구현.

SkillService.cs ISkillService.cs SkillVisualConfig.cs

스탯·재화·업그레이드

17종 스탯 합산 스냅샷, BigDouble 기반 큰 수 처리, 5종 재화(Gold/Emerald/Diamond/Ticket/Ruby), 4-Segment 비용 곡선 업그레이드.

StatService.cs CurrencyService.cs UpgradeService.cs NumberFormatUtil.cs

데이터 파이프라인

CSV → ScriptableObject 자동 변환 빌더, 제네릭 테이블 베이스(O(1) 인덱스), 9종 데이터 테이블, Addressables 배포.

DataTableBuilder.cs TableBase.cs GameDataSchemas.cs CsvUtil.cs

에디터 툴

비주얼 스폰 패턴 에디터, 디버그 SO(재화·업그레이드·스킬·가챠·장비), 커스텀 인스펙터 시스템.

SpawnPatternEditor.cs SpawnPatternCreator.cs DebugUpgradeSettingsEditor.cs DebugCurrencySettingsEditor.cs

팀원 역할 분담

다른 프로그래머가 뽑기(Gacha) / 장비(Equipment) / 드론(Drone) 시스템을 담당했으며, 기획 및 아트 담당 1명이 함께 작업합니다. 본 포트폴리오는 직접 설계·구현한 시스템만 기술합니다.

기술

기술 스택

Unity 6

6000.0.60f1

C#

.NET Standard

UniTask

비동기 처리 (Coroutine 대체)

Addressables

리소스 관리 · 비동기 로딩

DOTween

애니메이션 · 트위닝

BreakInfinity

BigDouble 큰 수 처리

Unity Localization

다국어 지원

DB기반 프로그래밍

SO와 CSV를 이용한 데이터 관리

전투

전투 시스템

스테이지 · 웨이브 · 다중 타겟 전투 · 패턴 스포닝 · 아웃라인 렌더링

전투 시연 영상 썸네일
실제 전투 예시

전투 시스템 연동 구조

CombatService (서비스 로직)

Pure C# 서비스. 스테이지/웨이브 진행, 공격 게이지 기반 자동 공격, 데미지 공식, 몬스터 스탯 조회를 담당합니다.

자동 공격 게이지 기본 0.5 공격/초 × (1 + AttackSpeed 보정). while 루프로 게이지 오버플로우 처리
터치 공격 초당 최대 2회 제한 (쿨다운 0.5초), TouchDamageMultiplier 적용
데미지 공식 (ATK × (1+ATKR) + ATKB) × TouchMul × CritMul — 크리티컬·울트라크리티컬 합산
몬스터 종류 결정 마지막 웨이브 시: 10스테이지마다 Boss, 그 외 Elite. 일반 웨이브는 Normal
HP 배율 Normal ×1, Elite ×10, Boss ×20. 시간 제한: Elite 20초, Boss 30초

CombatRunner (오케스트레이터)

MonoBehaviour 오케스트레이터. FSM(Moving/Fighting/Transition) 기반으로 플레이어 이동, 몬스터 교전 판정, 다중 타겟 공격 분배를 처리합니다.

FSM Phase 관리 WaitingForInit → Moving → Fighting → TransitionToMove 순환
다중 타겟 MaxTargetCount(기본 3, Evolution +1)만큼 동시 공격. 안전한 리스트 복사본 사용
교전 판정 X축 거리만 기준(AttackRange), Y축 수렴 옵션 분리. 0.5f 이하 시 강제 진입
웨이브 전환 패턴 완료 + 활성 몬스터 0 → 전환 타이머 후 다음 웨이브 시작

데미지 계산 공식 (CombatService)

private BigDouble CalculateDamage(bool isTouchAttack)
{
    var stats = _statService.GetSnapshot();

    // 기본 데미지 = (ATK × (1 + ATKR) + ATKB)
    BigDouble baseDmg = (stats.ATK * (1 + stats.ATKR)) + stats.ATKB;

    // 터치 배율
    if (isTouchAttack) baseDmg *= stats.TouchDamageMultiplier;

    // 크리티컬 판정
    bool isCritical = Random.value < (float)stats.CritRate;
    if (isCritical) baseDmg *= (1 + stats.CritDamage);

    // 울트라크리티컬 판정
    bool isUltra = isCritical && Random.value < (float)stats.UltraCritRate;
    if (isUltra) baseDmg *= 2.0;

    return baseDmg;
}

기획자 친화적 패턴 시스템

ScriptableObject + 커스텀 에디터로 기획자가 코드 없이 전투 패턴을 생성·수정할 수 있습니다

SpawnPattern (SO)

ScriptableObject로 스폰 포메이션을 정의합니다. SpawnSlot에 등장 순서(OrderOffset), Y위치(YNormalized), 몬스터 종류(MonsterKind)를 설정하여 다양한 패턴을 구성합니다.

Line ● ● ●
V-Formation ●  ↗ ● ●  ↘ ● ●
Diagonal ● ↘ ● ↘ ● ↘ ●
Swarm ●●● ●● ●
Boss Entry
// SpawnPattern — V-Formation 패턴 예시
new SpawnSlot(0f, 0f, MonsterKind.Normal)     // 선두 (중앙)
new SpawnSlot(0.5f, 0.4f, MonsterKind.Normal)  // 좌상단
new SpawnSlot(0.5f, -0.4f, MonsterKind.Normal) // 우하단
new SpawnSlot(1f, 0.7f, MonsterKind.Normal)    // 좌상단 끝
new SpawnSlot(1f, -0.7f, MonsterKind.Normal)   // 우하단 끝

SpawnPatternEditor (커스텀 인스펙터)

커스텀 에디터로 패턴을 시각적으로 편집할 수 있습니다. 그리드 위에 슬롯을 드래그&드롭으로 배치하고, 우클릭 컨텍스트 메뉴로 추가/삭제/복제합니다.

스폰 패턴 에디터 - 컨텍스트 메뉴 스폰 패턴 에디터 - 비주얼 에디터

▶ 구현된 패턴 실제 전투 화면 예시

실제 전투 화면 예시 실제 전투 화면 예시
드래그 편집 좌클릭 드래그로 슬롯 이동. Shift 키로 0.5/0.25 단위 스냅
컨텍스트 메뉴 우클릭으로 슬롯 추가/삭제/복제. 몬스터 종류별 색상 구분 (Normal, Elite, Boss)
원클릭 생성 SpawnPatternCreator 에디터 메뉴로 기본 패턴 5종 일괄 생성

SpawnPatternEditor — 비주얼 에디터 핵심 로직

[CustomEditor(typeof(SpawnPattern))]
public class SpawnPatternEditor : Editor
{
    private void DrawVisualEditor()
    {
        Rect graphRect = GUILayoutUtility.GetRect(0, 300f, GUILayout.ExpandWidth(true));
        DrawGrid(graphRect);     // 배경 그리드 렌더링
        HandleInput(graphRect);  // 마우스 드래그/우클릭 입력 처리
        DrawSlots(graphRect);    // 슬롯 포인트 시각화 (종류별 색상)
    }

    private void DrawSlots(Rect rect)
    {
        for (int i = 0; i < _spawnSlotsProp.arraySize; i++)
        {
            var kind = (MonsterKind)slot.FindPropertyRelative("MonsterKind").enumValueIndex;

            // 몬스터 종류별 색상: Normal=Cyan, Elite=Yellow, Boss=Red
            if (kind == MonsterKind.Elite) color = Color.yellow;
            if (kind == MonsterKind.Boss) color = Color.red;

            Handles.DrawSolidDisc(pos, Vector3.forward, HANDLE_SIZE / 2);
        }
    }
}

MonsterSpawner

패턴 기반 스폰 + 오브젝트 풀링. Wave별 패턴 수/화면 몬스터 제한을 지원하며, 대기/교전/사망 상태를 별도 관리합니다.

// 오브젝트 풀링 — Stack 기반 재사용
MonoObjectPool<MonsterUnitView> _monsterPool;

// 교전 상태 분리 관리
List<MonsterUnitView> _engagedMonsters;  // 전투 중
List<MonsterUnitView> _activeMonsters;   // 화면 상 전체

// 사망 → 비동기 풀 반환
async UniTaskVoid ReleaseMonsterDelayedAsync(monster, 0.5f)

CombatSettings (SO)

모든 전투 설정을 ScriptableObject로 중앙 관리. 웨이브별 설정(WaveConfig), 맵 경계 자동 계산, Y축 수렴 시스템, 몬스터 비주얼 가중치 등을 포함합니다.

CombatSettings 에디터 인스펙터 화면

몬스터 종류별 비주얼

일반 몬스터
Normal
기본 몬스터
일반 몬스터
Normal
기본 몬스터 todo 엘리트
일반 몬스터
Normal
기본 몬스터 todo 보스

몬스터 아웃라인 렌더링

URP ScriptableRendererFeature 기반 커스텀 아웃라인 — 3패스 렌더 파이프라인으로 구현

1

Mask Pass

아웃라인 대상 오브젝트를 단색(Alpha=1)으로 임시 텍스처에 렌더링

2

Copy Pass

현재 카메라 컬러를 복사하여 원본 보존

3

Composite Pass

마스크를 블러 처리 후 원본과 합성하여 아웃라인 생성

OutlineFeature

URP Renderer에 추가하는 ScriptableRendererFeature. RenderGraph API를 사용하여 효율적인 렌더 패스를 구성합니다.

조건부 패스 ActiveOutlines.Count == 0이면 패스 자체를 스킵 → 성능 절약
이벤트 타이밍 AfterRenderingTransparents에서 실행 — 투명 오브젝트 이후
OutlineFeature URP 설정 화면

OutlineObject

아웃라인을 표시할 오브젝트에 부착하는 컴포넌트. 3종 스타일과 색상/두께/글로우를 개별 설정합니다.

3종 스타일 Silhouette · WithInnerEdge · Highlight
전역 관리 static List<OutlineObject>로 활성 아웃라인 즉시 참조
에디터 미리보기 [ExecuteAlways]로 편집 모드에서도 실시간 확인
OutlineObject 인스펙터 설정 화면 아웃라인 적용 결과물

OutlineObject — 컴포넌트 설정

[ExecuteAlways]
[RequireComponent(typeof(Renderer))]
public class OutlineObject : MonoBehaviour
{
    // 전역 아웃라인 목록 (렌더러 패스에서 참조)
    private static readonly List<OutlineObject> _activeOutlines = new();
    public static IReadOnlyList<OutlineObject> ActiveOutlines => _activeOutlines;

    [Header("아웃라인 스타일")]
    [SerializeField] private OutlineStyle _style = OutlineStyle.Silhouette;
    [SerializeField] private Color _color = Color.white;

    [Header("아웃라인 설정")]
    [SerializeField, Range(0.5f, 10f)] private float _width = 2f;
    [SerializeField, Range(0f, 5f)] private float _glowIntensity = 1f;

    private void OnEnable()
    {
        Renderer = GetComponent<Renderer>();
        if (!_activeOutlines.Contains(this))
            _activeOutlines.Add(this);
    }

    private void OnDisable() => _activeOutlines.Remove(this);
}

UnitView (Base Class)

플레이어·몬스터 공통 비주얼 추상 클래스. 상태(Move/Attack/Dead), 공격 애니메이션 대기(UniTask), Z축 깊이 정렬(SortingOrder 대체)을 관리합니다.

// Z축 깊이 정렬 — SortingOrder 대신 사용
private void LateUpdate()
{
    var pos = transform.position;
    pos.z = pos.y * 0.01f;  // Y→Z 변환
    transform.position = pos;
}

CombatInputHandler

터치/마우스 입력 처리 전용 컴포넌트. UI 터치 필터링 포함. 교전 중인 몬스터 수를 트래킹하여 CombatService.TryApplyTouchAttack()에 전달합니다.

// UI 위 터치 필터링 + 터치 공격 시도
if (eventSystem.IsPointerOverGameObject()) return;
_combatService.TryApplyTouchAttack(_engagedMonsterCount);

MonsterUnitView

몬스터 개별 스탯(HP, 방어력, 레벨) 관리. 방어력 적용 + 방무 비율 계산으로 최종 데미지를 산출합니다.

// 데미지 계산 (방어력 적용)
public BigDouble TakeDamage(BigDouble rawDamage, double ignoreRate)
{
    BigDouble effectiveDef = _defense * (1.0 - ignoreRate);
    BigDouble finalDmg = rawDamage / (1 + effectiveDef * 0.01);
    _currentHp -= finalDmg;
    return finalDmg;
}
스킬

스킬 시스템 UI 및 시각 효과

동적 스킬 트리 · UI 전장의 안개(Fog of War) 제어 · 상태 시각화

스킬 · 스탯 · 재화 연동 구조

스킬 트리 전체 화면 — Fog of War 적용
인게임 스크린샷 Fog of War가 적용된 스킬 트리 · 해금 영역이 부드럽게 드러남
Locked
선행 노드 해금 →
Unlockable
에메랄드 소모 →
Researching
타이머 완료 →
Unlocked

SkillService — 동적 스킬 트리 구축

하드코딩 위치 배치 없이 SkillTable (CSV)의 좌표(XCoord, YCoord) 데이터를 활용해 스킬 슬롯들을 동적으로 배치합니다. 맨해튼 거리가 1인 인접 노드를 식별(상/하/좌/우)해 양방향 연결선(Line) 오브젝트를 자동으로 생성합니다.

CSV 좌표 데이터 SkillTable CSV 데이터 표
노드 배치 원리 스킬 노드 좌표 → 트리 배치 원리
로마자 자동 추출 이름(예: "자동화 II")에서 레벨 텍스트를 파싱하여 인게임 UI 슬롯 우측 하단에 로마자 레벨 포맷으로 자동 반영합니다(ExtractRomanNumeralFromName).
효과 유형 (EffectType) Stat: StatService에 StatModifier로 적용 (Rate 보정)
Special: SkillSpecialType으로 특수 효과 합산 (AutoTouch, Execute 등 16종)
상태 저장/로드 및 복원 해금 목록 + 연구 중인 스킬 + NEW 태그 → JSON 파일. 앱 재시작 시 타이머 자동 복원.

UI 전장의 안개 (Fog of War)

Unity 6.0 URP 환경에서 작동하는 Texture2D 픽셀 수동 조작 방식의 안개 시스템입니다.

타원 마스킹 알고리즘 (dx/rx)² + (dy/ry)² 방정식으로 종횡비를 유지하며 가장자리를 부드럽게 마스킹
EdgeSoftness 그라디언트 경계부의 알파 값을 Lerp로 보간하여 자연스러운 페이드 효과 구현
FogRevealer 컴포넌트 해금된 슬롯에 부착 → FogOfWarManager에 좌표 등록 → 안개 걷힘

상태별 UI 시각화 · 팝업

Locked — 어둡게 디밍 + 자물쇠 아이콘 표시
Unlockable — 파란 글로우 테두리 강조
Researching — Radial Fill 원형 프로그레스
Unlocked — 풀 아이콘 + 레벨 로마자 표시
UniTask 비동기 연구 타이머 StartResearchTimerAsync로 연구 시간 대기 후 자동 해금. 앱 재시작 시 DateTime.Ticks 기반 남은 시간 복원.
EventBus 상태 전파 SkillStateChangedEvent 발행 → FogRevealer 토글, UI 슬롯 갱신, 스탯 재계산이 모두 느슨하게 연결됩니다.
데이터 드리븐 트리 CSV 좌표 수정만으로 스킬 트리 레이아웃 변경 가능. 코드 수정 없이 기획단에서 구조를 제어합니다.

스킬 해금 로직 — TryUnlock()

public bool TryUnlock(string skillId)
{
    if (!CanUnlock(skillId)) return false;

    // 에메랄드 소모
    if (!_currencyService.TryConsume(CurrencyType.Emerald, row.Cost, $"UnlockSkill_{skillId}"))
        return false;

    if (row.Time > 0)
    {
        // 연구 시작 → UniTask.Delay 비동기 대기
        _researchingSkills.Add(new ResearchInfo { SkillID = skillId, EndTimeTicks = endTime });
        StartResearchTimerAsync(skillId, row.Time).Forget();
        _eventBus.Publish(new SkillStateChangedEvent(skillId, SkillState.Researching));
    }
    else
    {
        // 즉시 해금
        _unlockedSkillIds.Add(skillId);
        ApplyPassiveStats();
        _eventBus.Publish(new SkillStateChangedEvent(skillId, SkillState.Unlocked));
    }
    return true;
}
스탯·재화

스탯 · 재화 · 업그레이드

17종 스탯 · BigDouble 큰 수 · 4-Segment 비용 곡선

StatService — 스냅샷 기반 스탯 합산

업그레이드 레벨 → StatsTable 조회 → 장비 모디파이어 → 스킬 모디파이어를 순차 적용하여 CharacterStats 스냅샷을 생성합니다. 인게임 스탯 세부 UI는 별도로 존재하지 않으며, 커스텀 인스펙터(디버그 환경)를 통해 모든 스탯의 실시간 적용 값을 확인하고 제어할 수 있도록 구축되었습니다.

스탯 디버그 UI 화면
공격 계열
ATK (공격력) ATKR (공격력%) ATKB (공격 보너스) ATKSP (공격 속도) ATKT (터치 데미지%) CR (크리티컬 확률) CD (크리티컬 데미지) UCR (울트라크리티컬) IGNDEF (방무%)
방어 계열
HP (체력) DEF (방어력) DEFR (방어력%) HPREC (HP 재생)
유틸리티
GOLDR (골드 보너스%) OFFT (오프라인 시간) OFFA (오프라인 보상%) RCD (쿨다운 감소)
// BigDouble 가수부·지수부 분리 계산
private BigDouble ToBigDouble(double mantissa, double pow)
{
    var exponent = new BigDouble(Math.Pow(10d, pow));
    return new BigDouble(mantissa) * exponent;
}

// 스냅샷 재계산 흐름
RecalculateSnapshot()
    → BuildBaseStatsFromLevels()   // 업그레이드 레벨별 StatsTable 조회
    → ApplyModifiers(equipment)     // 장비 Flat/Rate 보정
    → ApplyModifiers(skill)         // 스킬 Rate 보정

CurrencyService

5종 재화(Gold, Emerald, Diamond, Ticket, Ruby) 관리. BigDouble 문자열 직렬화, EventBus 이벤트 발행(지급/소모), 오프라인 보상 계산을 처리하며, 재화 모델 변경 시 UI 위젯 등에서 이벤트를 구독하여 즉각 반영하도록 설계했습니다.

재화 인게임 UI 화면 재화 디버그 UI 화면
오프라인 보상 최소 300초 이상 미접속 시 지급. 시간 상한(OFFT), 골드 보너스율, 오프라인 보너스율 적용
BigDouble 직렬화 정밀도 유지를 위해 BigDouble.ToString()BigDouble.Parse() 문자열 저장

UpgradeService

4-Segment 비용 곡선으로 레벨 구간별 성장률을 차등 적용합니다. 다중 레벨 구매, 비용 지불 가능 여부 실시간 확인을 제공하며 적용 즉시 StatService 스냅샷 갱신을 트리거합니다.

업그레이드 인게임 UI 화면 업그레이드 디버그 커스텀 인스펙터
// 비용 공식
cost = GoldBase
     × GoldPow^level
     × (1 + Seg1Growth)^seg1Levels
     × (1 + Seg2Growth)^seg2Levels
     × (1 + Seg3Growth)^seg3Levels
     × (1 + Seg4Growth)^seg4Levels

큰 수 처리 (BreakInfinity)

  • BigDouble struct: GC 할당 없는 무한 정밀도 수치 표현 (가수부 + 지수부)
  • NumberFormatUtil: 1000단위 알파벳 표기 (1.2A → 1.5B → 1.3C), AA/AB 확장, 로마자 변환 지원
  • JSON 직렬화: string 형태("1.23e45")로 정밀도 손실 없이 저장/로드
아키텍처

코어 아키텍처

ServiceLocator 패턴 기반의 서비스 지향 아키텍처

프레젠테이션 계층
UIManager
UI_Popup
UI_Scene
게임플레이 계층
CombatRunner
MonsterSpawner
UnitView
▼ ServiceLocator ▼
서비스 계층 (Pure C#, 인터페이스 기반)
CombatService
StatService
CurrencyService
UpgradeService
SkillService
ConfigService
데이터 계층
ResourceManager
EventBus
TableBase<K,V>

ServiceLocator

인터페이스 기반 서비스 등록·조회. RuntimeInitializeOnLoadMethod로 Fast Play Mode 대응. 제네릭 타입 안전성과 동적 등록 모두 지원.

// 제네릭 타입 안전 등록
ServiceLocator.Register<IStatService, StatService>(statService);

// 서비스 조회
var stats = ServiceLocator.Get<IStatService>();

GameManager

MonoSingleton<T> 기반 진입점. 12개 서비스를 의존성 순서에 맞게 비동기 등록하며, 로딩 진행도(IProgress<float>)를 UI에 보고. 최소 로딩 시간 보장.

// 서비스 등록 순서 (의존성 그래프)
ResourceManager → EventBus → ConfigService
→ StatService → CurrencyService → UpgradeService
→ CombatService → SkillService → ...

EventBus

제네릭 struct 기반 이벤트 시스템으로 GC 할당 제로. Publish/Subscribe 패턴으로 시스템 간 느슨한 결합 달성.

// struct 이벤트 → GC 제로
public struct EnemyDefeatedEvent {
    public int StageIndex;
    public MonsterKind MonsterKind;
    public CombatReward Reward;
}
_eventBus.Publish(new EnemyDefeatedEvent { ... });

ObjectPool<T>

MonoObjectPool<T>로 MonoBehaviour 전용 풀링 구현. Get/Release 콜백, 최대 크기 제한, 초기 풀 프리워밍 지원.

public class MonoObjectPool<T> : IObjectPool<T>
    where T : MonoBehaviour
{
    // Stack 기반 풀링 + HashSet 활성 객체 추적
    private readonly Stack<T> _pool = new();
    private readonly HashSet<T> _activeObjects = new();
}

핵심 설계 원칙

  • 인터페이스 분리: 모든 서비스는 IXxxService 인터페이스를 통해 접근 → 테스트·교체 용이
  • 비동기 전용: Coroutine 사용 금지, 모든 비동기 로직은 UniTask 기반
  • DontDestroyOnLoad: MonoSingleton<T>가 씬 전환 시에도 유지
  • Save/Load 일관성: 모든 서비스가 SaveAsync()/LoadAsync() 패턴을 공유하며 OnApplicationPause/Quit에서 자동 저장
데이터

데이터 파이프라인

CSV → ScriptableObject 자동 변환 · 9종 테이블

CSV (Source of Truth)
기획자 Google Sheets에서 Export
DataTableBuilder
에디터 메뉴: Tools/Build Data Tables
TableBase<K,V> SO
Dictionary 인덱스 O(1) 조회
Addressables
비동기 로딩 · 메모리 관리

CSV → ScriptableObject 변환 예시

Google Sheets에서 Export한 CSV 원본과, DataTableBuilder가 자동 파싱하여 생성한 ScriptableObject 에셋

StatsTable 17종 스탯 · 1.6MB
CSV 원본 StatsTable CSV 원본
파싱된 SO StatsTable 파싱된 ScriptableObject
SkillTable 좌표 · 비용 · 효과
CSV 원본 SkillTable CSV 원본
파싱된 SO SkillTable 파싱된 ScriptableObject
UpgradeTable 4-Segment 비용 곡선
CSV 원본 UpgradeTable CSV 원본
파싱된 SO UpgradeTable 파싱된 ScriptableObject

9종 데이터 테이블

MonsterTable Key: MonsterLevel (int) HP, ATK, DEF, Gold 등 레벨별 몬스터 스탯
StatsTable Key: Level (int) 17종 스탯 레벨별 Base/Pow 수치 (1.6MB CSV)
UpgradeTable Key: Code (string) 업그레이드 비용 곡선, 4-Segment 성장률
SkillTable Key: ID (string) 스킬 좌표, 비용, 연구시간, 효과 타입/값
CurrencyTable Key: CurrencyType (enum) 재화별 설정 데이터
EvolutionTable Key: EvolutionLevel (int) 진화 레벨별 조건 및 보너스
EquipmentTable Key: Code (string) 장비 옵션/등급 (팀원 담당)
GachaEquipmentTable Key: Level (int) 장비 뽑기 확률 (팀원 담당)
GachaDroneTable Key: Level (int) 드론 뽑기 확률 (팀원 담당)

TableBase<TKey, TValue> — 제네릭 테이블 베이스

모든 테이블 SO의 공통 부모. List<T> 직렬화 + Dictionary<K,V> 런타임 인덱스를 OnEnable()에서 자동 구성합니다.

public abstract class TableBase<TKey, TValue> : ScriptableObject
{
    [SerializeField] private List<TValue> _rows = new();
    [NonSerialized] private readonly Dictionary<TKey, TValue> _index = new();

    protected abstract TKey GetKey(TValue value);  // 각 테이블이 키 추출 로직 구현

    protected virtual void OnEnable() => BuildIndex();  // SO 로드 시 자동 인덱싱

    public void SetRows(List<TValue> rows)  // 에디터 빌더 진입점
    {
        _rows = rows ?? new List<TValue>();
        BuildIndex();
    }
}
에디터

에디터 툴

스폰 패턴 비주얼 에디터 · 디버그 ScriptableObject

SpawnPatternEditor — 비주얼 패턴 에디터

[CustomEditor(typeof(SpawnPattern))] 기반 인스펙터. 그리드 배경 위에 스폰 슬롯을 시각적으로 배치·편집할 수 있는 인터랙티브 에디터입니다.

비주얼 그리드X축(등장 순서) × Y축(맵 상대 위치)을 시각적으로 편집
드래그 & 드롭마우스로 슬롯 위치 조정, 우클릭 컨텍스트 메뉴(추가/삭제/복제)
좌표 변환Rect ↔ Graph 좌표 변환 헬퍼 함수 내장
스폰 패턴 비주얼 에디터 화면 1 스폰 패턴 비주얼 에디터 화면 2

SpawnPatternCreator

기본 스폰 패턴 5종(Line, V-Formation, Diagonal, Swarm, BossEntry)을 메뉴 한 번으로 자동 생성하는 에디터 유틸리티.

DebugUpgradeSettingsEditor

업그레이드 레벨 강제 설정, 전체 초기화, 전체 MAX, 비용 계산 미리보기를 인스펙터에서 제공하는 디버그 SO.

DebugUpgradeSettings 인스펙터 화면

DebugCurrencySettingsEditor

5종 재화 잔액 조회/추가/차감, 오프라인 보상 시뮬레이션 등을 인스펙터에서 제공하는 디버그 SO.

DebugCurrencySettings 인스펙터 화면

DebugSkillSettingsEditor

스킬 강제 해금/잠금, 전체 초기화, 연구 타이머 확인 등 스킬 시스템 디버깅용 커스텀 인스펙터.

DebugSkillSettings 인스펙터 화면

DebugStatSettingsEditor

현재 스탯 스냅샷 실시간 조회, 모디파이어 목록 확인, 스탯 강제 변경 등 스탯 시스템 디버깅용 SO.

DebugStatSettings 인스펙터 화면

에디터 메뉴

메뉴 경로 기능 파일
Tools/SahurRaising/Build Data Tables CSV → SO 변환 (9종 테이블 일괄 빌드) DataTableBuilder.cs
Tools/SahurRaising/Combat/Create Default Spawn Patterns 기본 스폰 패턴 5종 자동 생성 SpawnPatternCreator.cs
Tools/SahurRaising/Data/Localization Importer 다국어 CSV 임포트 LocalizationImporterWindow.cs
구조 · 협업

프로젝트 구조 및 협업

3인 팀의 Git 기반 협업 워크플로우와 프로젝트 디렉터리 구조

Git 커밋 히스토리

팀원별 커밋 컨벤션을 통한 체계적 버전 관리 — [이름] 작업 내용 형식으로 작업자 식별

Git 커밋 히스토리 — 최근 커밋
Git 커밋 히스토리 — 기능 개발
Git 커밋 히스토리 — 중반 개발
Git 커밋 히스토리 — 초기 세팅

디렉터리 구조

기능별 모듈화된 프로젝트 레이아웃

Assets/
├── 02. Scripts/
│   ├── Core/                          ← 코어 아키텍처
│   │   ├── GameManager.cs                 진입점 · 서비스 초기화
│   │   ├── ServiceLocator.cs              서비스 등록/조회
│   │   ├── EventBus.cs                    이벤트 시스템
│   │   ├── MonoSingleton.cs               제네릭 싱글톤
│   │   ├── ObjectPool.cs                  오브젝트 풀링
│   │   ├── ResourceManager.cs             Addressables 래퍼
│   │   ├── Events.cs                      이벤트 struct 정의
│   │   ├── Data/                          데이터 스키마
│   │   │   ├── GameDataSchemas.cs         전역 enum/struct 정의
│   │   │   ├── TableBase.cs               제네릭 테이블 베이스
│   │   │   ├── MonsterTable.cs            몬스터 테이블
│   │   │   ├── StatsTable.cs              스탯 테이블
│   │   │   ├── UpgradeTable.cs            업그레이드 테이블
│   │   │   ├── SkillTable.cs              스킬 테이블
│   │   │   └── CurrencyTable.cs           재화 테이블
│   │   └── Services/
│   │       ├── Combat/
│   │       │   ├── CombatInterfaces.cs    인터페이스 + struct
│   │       │   ├── CombatService.cs       전투 로직 서비스
│   │       │   ├── StatService.cs         스탯 합산 서비스
│   │       │   ├── CurrencyService.cs     재화 관리 서비스
│   │       │   ├── UpgradeService.cs      업그레이드 서비스
│   │       │   └── SkillService.cs        스킬 서비스
│   │       └── Config/
│   │           ├── ConfigService.cs       설정 서비스
│   │           └── IConfigService.cs      인터페이스
│   ├── GamePlay/                      ← 전투 컴포넌트 (MonoBehaviour)
│   │   ├── CombatRunner.cs                전투 오케스트레이터 FSM
│   │   ├── MonsterSpawner.cs              패턴 기반 스폰 + 풀링
│   │   ├── CombatSettings.cs              전투 설정 SO
│   │   ├── SpawnPattern.cs                스폰 포메이션 SO
│   │   ├── UnitView.cs                    유닛 비주얼 Base
│   │   ├── PlayerUnitView.cs              플레이어 뷰
│   │   ├── MonsterUnitView.cs             몬스터 뷰
│   │   └── CombatInputHandler.cs          입력 처리
│   ├── UI/                            ← UI 시스템
│   │   ├── UIManager.cs                   UI 생명주기 관리
│   │   ├── UI_Base.cs / UI_Popup.cs       UI 베이스 클래스
│   │   └── Popup/ Scene/                  팝업/씬 UI
│   ├── Utils/                         ← 유틸리티
│   │   ├── NumberFormatUtil.cs            BigDouble 포맷팅
│   │   └── StringUtil.cs                  문자열 유틸
│   └── Debug/                         ← 디버그 SO
│       ├── DebugCurrencySettings.cs
│       ├── DebugUpgradeSettings.cs
│       ├── DebugSkillSettings.cs
│       └── Editor/                        커스텀 인스펙터
├── Editor/                            ← 에디터 전용
│   ├── DataTableBuilder.cs                CSV → SO 빌더
│   ├── SpawnPatternEditor.cs              패턴 비주얼 에디터
│   ├── SpawnPatternCreator.cs             기본 패턴 생성기
│   └── CsvUtil.cs                         CSV 파서
├── 06. ScriptableObject/              ← SO 에셋
│   ├── Data/                              테이블 SO (9종)
│   ├── Combat/                            전투 설정 SO
│   └── Debug/                             디버그 SO
└── 10. Data/                          ← CSV 원본 (Source of Truth)
    ├── AI 로봇 키우기 DB - Monster.csv
    ├── AI 로봇 키우기 DB - Stats.csv     (1.6MB, 대량 레벨 데이터)
    ├── AI 로봇 키우기 DB - Upgrade.csv
    ├── AI 로봇 키우기 DB - Skill.csv
    └── ...총 9개 CSV 파일