1. 프로젝트 구조 설계

Assets/
├── Runtime/
│   ├── Resources/
│   │   └── Data/
│   │       ├── Stages/     # 스테이지 데이터
│   │       ├── Monsters/   # 몬스터 데이터
│   │       ├── Skills/     # 스킬 데이터
│   │       └── DropTables/ # 드롭테이블 데이터
│   └── Scripts/
│       ├── Systems/        # 게임 시스템
│       └── Utils/          # 유틸리티
└── Editor/
    └── GameSystemEditor.cs # 시스템 관리자Assets/
├── Runtime/
│   ├── Resources/
│   │   └── Data/
│   │       ├── Stages/     # 스테이지 데이터
│   │       ├── Monsters/   # 몬스터 데이터
│   │       ├── Skills/     # 스킬 데이터
│   │       └── DropTables/ # 드롭테이블 데이터
│   └── Scripts/
│       ├── Systems/        # 게임 시스템
│       └── Utils/          # 유틸리티
└── Editor/
    └── GameSystemEditor.cs # 시스템 관리자

 

2. 기본 에디터 윈도우 구현

 

public class GameSystemEditor : OdinEditorWindow
{
    private const string BASE_PATH = "Assets/Runtime/Resources/Data";
    private const string STAGES_PATH = BASE_PATH + "/Stages";
    private const string MONSTERS_PATH = BASE_PATH + "/Monsters";
    private const string SKILLS_PATH = BASE_PATH + "/Skills";
    private const string DROPS_PATH = BASE_PATH + "/DropTables";

    [MenuItem("Game/시스템 관리자")]
    private static void OpenWindow()
    {
        var window = GetWindow<GameSystemEditor>();
        window.titleContent = new GUIContent("게임 시스템 관리자");
        window.Show();
        CreateRequiredDirectories();
    }

    private static void CreateRequiredDirectories()
    {
        string[] paths = { STAGES_PATH, MONSTERS_PATH, SKILLS_PATH, DROPS_PATH };
        foreach (var path in paths)
        {
            if (!AssetDatabase.IsValidFolder(path))
            {
                CreateDirectory(path);
            }
        }
        AssetDatabase.Refresh();
    }
}

 

3. 데이터 관리 기본 구조

public class GameSystemEditor : OdinEditorWindow
{
    [TabGroup("스테이지")]
    [ListDrawerSettings(ShowIndexLabels = true)]
    public List<StageData> allStages = new List<StageData>();

    [TabGroup("몬스터")]
    [ListDrawerSettings(ShowIndexLabels = true)]
    public List<MonsterData> monsterDatas = new List<MonsterData>();

    [TabGroup("스킬")]
    [ListDrawerSettings(ShowIndexLabels = true)]
    public List<SkillData> skillDatas = new List<SkillData>();

    protected override void OnEnable()
    {
        base.OnEnable();
        LoadAllData();
    }

    private void LoadAllData()
    {
        allStages = new List<StageData>(Resources.LoadAll<StageData>("Data/Stages"));
        monsterDatas = new List<MonsterData>(Resources.LoadAll<MonsterData>("Data/Monsters"));
        skillDatas = new List<SkillData>(Resources.LoadAll<SkillData>("Data/Skills"));
    }
}

 

Part 2: 프리뷰 시스템 구현

 

1. 프리뷰 클래스 구현

[Serializable]
public class MonsterPreview
{
    [PreviewField(150)]
    [HorizontalGroup("Preview", Width = 150)]
    [LabelText("3D 모델 프리뷰")]
    public GameObject monsterModel;

    [BoxGroup("스탯")]
    [LabelText("체력")]
    [SuffixLabel("$healthSuffix", Overlay = true)]
    public double health = 1000;

    private string healthSuffix => FormatNumber(health);

    private string FormatNumber(double number)
    {
        if (number >= 1e12) return $"{number / 1e12:F2}T";
        if (number >= 1e9) return $"{number / 1e9:F2}B";
        if (number >= 1e6) return $"{number / 1e6:F2}M";
        if (number >= 1e3) return $"{number / 1e3:F2}K";
        return number.ToString("F0");
    }
}

 

2. 스킬 프리뷰 구현

[Serializable]
public class SkillPreview
{
    [PreviewField(100)]
    [HorizontalGroup("Preview", Width = 100)]
    [LabelText("스킬 아이콘")]
    public Sprite skillIcon;

    [PreviewField(150)]
    [HorizontalGroup("Preview", Width = 150)]
    [LabelText("이펙트 프리뷰")]
    public GameObject effectPrefab;

    [BoxGroup("스탯")]
    [LabelText("데미지")]
    public double damage = 50;

    [BoxGroup("설정")]
    [LabelText("기본 자동사용")]
    public bool defaultAutoMode = true;
}

 

Part 3: 데이터 관리 기능

 

1. 데이터 생성 기능

[TabGroup("스킬")]
[Button("새 스킬 생성")]
private void CreateNewSkill()
{
    var skillData = CreateInstance<SkillData>();
    string path = $"{SKILLS_PATH}/NewSkill_{skillDatas.Count + 1}.asset";

    AssetDatabase.CreateAsset(skillData, path);
    AssetDatabase.SaveAssets();
    skillDatas.Add(skillData);

    Selection.activeObject = skillData;
    EditorGUIUtility.PingObject(skillData);
}

 

2. 데이터 검증 시스템

[TabGroup("시스템 설정")]
[Button("데이터 유효성 검사")]
private void ValidateAllData()
{
    StringBuilder errors = new StringBuilder();

    foreach (var skill in skillDatas)
    {
        if (skill.effectPrefab == null)
            errors.AppendLine($"스킬 '{skill.name}': 이펙트 프리팹이 없습니다.");
        if (skill.cooldown <= 0)
            errors.AppendLine($"스킬 '{skill.name}': 쿨다운이 0 이하입니다.");
    }

    string errorMessage = errors.ToString();
    if (string.IsNullOrEmpty(errorMessage))
        EditorUtility.DisplayDialog("검증 완료", "모든 데이터가 유효합니다.", "확인");
    else
        EditorUtility.DisplayDialog("검증 실패", errorMessage, "확인");
}

 

3. 데이터 내보내기/가져오기

private void ExportData()
{
    string path = EditorUtility.SaveFolderPanel("데이터 내보내기", "", "");
    if (string.IsNullOrEmpty(path)) return;

    if (editor != null)
    {
        ExportListToJson(editor.allStages, Path.Combine(path, "Stages.json"));
        ExportListToJson(editor.monsterDatas, Path.Combine(path, "Monsters.json"));
        ExportListToJson(editor.skillDatas, Path.Combine(path, "Skills.json"));
    }
}

private void ExportListToJson<T>(List<T> list, string path)
{
    string json = JsonUtility.ToJson(new SerializableList<T> { items = list }, true);
    File.WriteAllText(path, json);
}

 

Part 4: 도움말 시스템

 

1. 도움말 텍스트 구현

[TabGroup("도움말")]
[HideLabel]
[TextArea(10, 30)]
[ShowInInspector]
private string helpGuide = @"
[스테이지 관리]
- 새 스테이지 생성: '새 스테이지 생성' 버튼으로 새로운 스테이지를 만듭니다.
- 스테이지 수정: '현재 스테이지'에서 선택한 스테이지의 속성을 수정합니다.
...";

 

2. PDF 및 온라인 문서 연동

[TabGroup("도움말")]
[Button("도움말 PDF 열기")]
private void OpenHelpPDF()
{
    string pdfPath = "Assets/Documentation/GameSystemGuide.pdf";
    if (File.Exists(pdfPath))
    {
        System.Diagnostics.Process.Start(pdfPath);
    }
    else
    {
        EditorUtility.DisplayDialog("알림", "도움말 PDF 파일을 찾을 수 없습니다.", "확인");
    }
}

 

학습 내용 및 성과

1. Unity 에디터 확장 개발 방법 습득

2. Odin Inspector를 활용해봄

3. ScriptableObject 기반 데이터 관리 시스템 구축

4. 사용자 친화적인 에디터 도구 개발

 

향후 계획

1. 데이터 간 연관 관계 시각화 기능

2. 데이터 버전 관리 시스템

3. 실시간 협업을 위한 데이터 동기화

 

 

 

 

개선버전

아직 사소한 문제가 있지만 작동은 잘 된다.