커스텀 에디터 모듈: 기획자를 위한 아이템 드롭률 및 스킬 범위 시각화 툴 구현

커스텀 에디터 모듈: 기획자를 위한 아이템 드롭률 및 스킬 범위 시각화 툴 구현

기획자가 에디터 상에서 스킬 사거리와 아이템 드롭 확률 분포를 직관적으로 확인하고 편집할 수 있도록 돕는 Unity 커스텀 에디터 시각화 툴 구현 방식을 소개합니다.

에디터 시각화 툴이 필요한 이유

게임 기획 및 밸런싱 작업에서 스킬 사거리, 효과 범위, 몬스터 처치 시 아이템 드롭 영역과 같은 공간 데이터는 숫자로만 관리하기 어렵습니다. 기획자가 인스펙터(Inspector) 창에서 사거리 15m, 각도 60도, 드롭 반경 10m라는 수치를 수정할 때마다 실행 모드(Play Mode)에 진입하여 테스트하는 방식은 작업 효율을 크게 저하시킵니다.

유니티(Unity)의 커스텀 에디터(Custom Editor)와 Handles, SceneView API를 활용하면 씬 뷰(Scene View) 내부에서 기획 데이터를 직관적인 그래픽 형태로 실시간 렌더링하고 마우스 드래그로 범위를 직접 조작하는 에디팅 환경을 구축할 수 있습니다.

flowchart LR
    A[기획자 데이터 수정] --> B[CustomEditor OnSceneGUI 감지]
    B --> C[Handles 및 Gizmos 렌더링]
    C --> D[SceneView 실시간 시각화]
    D --> E[Undo 시스템 연동 및 데이터 저장]

스킬 범위 및 효과 감쇄 시각화 (Handles API)

스킬의 최대 사거리와 유효 부채꼴 범위 그리고 거리에 따른 데미지 감쇄 비율을 시각화하는 커스텀 에디터를 작성합니다. 단순히 원을 그리는 것을 넘어 거리 감쇄 공식을 시각적 색상 그라데이션으로 표현하면 기획자가 감쇄 경계선을 한눈에 파악할 수 있습니다.

거리 감쇄 수식은 다음과 같은 멱함수 형태를 주로 사용합니다.

P(r)=Pmax(1rRmax)γP(r) = P_{\max} \cdot \left(1 - \frac{r}{R_{\max}}\right)^\gamma

여기서 r은 중심으로부터의 거리, R_max는 최대 사거리, γ는 감쇄 지수입니다. 이 수식을 씬 뷰 렌더링과 연결하여 원형 감쇄 반경을 그리는 컴포넌트와 커스텀 에디터 코드 구조는 다음과 같습니다.

using UnityEngine;

public class SkillAreaComponent : MonoBehaviour
{
    [Range(1f, 50f)] public float maxRadius = 15f;
    [Range(0f, 180f)] public float angle = 60f;
    [Range(0.1f, 5f)] public float decayExponent = 1.5f;
    public Color primaryColor = new Color(1f, 0.3f, 0.2f, 0.4f);
}

이제 해당 컴포넌트의 데이터를 에디터 상에서 그리는 CustomEditor 클래스를 작성합니다. OnSceneGUI 메서드 내부에서 Handles.DrawSolidArc와 Handles.RadiusHandle을 결합하면 직관적인 조작 핸들이 생성됩니다.

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(SkillAreaComponent))]
public class SkillAreaEditor : Editor
{
    private void OnSceneGUI()
    {
        SkillAreaComponent skill = (SkillAreaComponent)target;
        Transform t = skill.transform;

        // 사거리 조작 핸들
        EditorGUI.BeginChangeCheck();
        Handles.color = skill.primaryColor;
        float newRadius = Handles.RadiusHandle(Quaternion.identity, t.position, skill.maxRadius);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(skill, "Change Skill Radius");
            skill.maxRadius = newRadius;
        }

        // 부채꼴 유효 범위 시각화
        Vector3 fromDirection = Quaternion.Euler(0, -skill.angle * 0.5f, 0) * t.forward;
        Handles.color = new Color(skill.primaryColor.r, skill.primaryColor.g, skill.primaryColor.b, 0.15f);
        Handles.DrawSolidArc(t.position, Vector3.up, fromDirection, skill.angle, skill.maxRadius);

        // 외곽선 그리기
        Handles.color = skill.primaryColor;
        Handles.DrawWireArc(t.position, Vector3.up, fromDirection, skill.angle, skill.maxRadius);
        
        // 텍스트 라벨 표시
        Handles.Label(t.position + t.forward * skill.maxRadius, $"Radius: {skill.maxRadius:F1}m\nAngle: {skill.angle:F0}°");
    }
}

Unity 씬 뷰에서 스킬 사거리와 부채꼴 효과 범위가 Handles 기즈모로 시각화된 모습

아이템 드롭률 분포 시각화 툴

특정 지역이나 몬스터 스폰 영역 내에서 위치별 아이템 드롭 확률 분포를 시각화하는 작업 역시 에디터 툴의 핵심 기능입니다. 중앙 영역일수록 드롭률이 높고 외곽으로 갈수록 낮아지는 가중치 분포를 라벨과 그리드 셰이프 기반으로 시각화할 수 있습니다.

using UnityEngine;
using UnityEditor;

public class ItemDropZoneComponent : MonoBehaviour
{
    public float innerRadius = 5f;
    public float outerRadius = 12f;
    [Range(0f, 100f)] public float baseDropRate = 85f;
}

[CustomEditor(typeof(ItemDropZoneComponent))]
public class ItemDropZoneEditor : Editor
{
    private void OnSceneGUI()
    {
        ItemDropZoneComponent zone = (ItemDropZoneComponent)target;
        Vector3 center = zone.transform.position;

        // 내각 고확률 영역 (Green)
        Handles.color = new Color(0.2f, 0.9f, 0.3f, 0.2f);
        Handles.DrawSolidDisc(center, Vector3.up, zone.innerRadius);
        Handles.color = Color.green;
        Handles.DrawWireDisc(center, Vector3.up, zone.innerRadius);

        // 외각 감쇄 영역 (Yellow)
        Handles.color = new Color(0.9f, 0.7f, 0.1f, 0.1f);
        Handles.DrawSolidDisc(center, Vector3.up, zone.outerRadius);
        Handles.color = Color.yellow;
        Handles.DrawWireDisc(center, Vector3.up, zone.outerRadius);

        // 정보 라벨 출력
        GUIStyle style = new GUIStyle();
        style.normal.textColor = Color.white;
        style.fontSize = 12;
        style.fontStyle = FontStyle.Bold;

        Handles.Label(center + Vector3.right * (zone.innerRadius * 0.5f), $"Inner Drop Rate: {zone.baseDropRate}%", style);
        Handles.Label(center + Vector3.right * (zone.outerRadius * 0.8f), $"Outer Drop Rate: {zone.baseDropRate * 0.3f:F1}%", style);
    }
}

아이템 드롭 영역과 확률 density 가중치 분포가 에디터 화면에 출력된 모습

에디터 시각화 툴 최적화 및 주의점

에디터 스크립팅 과정에서 씬 뷰 렌더링 성능과 에디터 반응성을 유지하기 위해 반드시 고려해야 하는 요소들이 존재합니다.

  1. EditorGUI.BeginChangeCheck와 Undo 연동: 핸들을 마우스로 드래그할 때 매 프레임 데이터가 변경되므로 변경 감지 블록을 사용하고 Undo.RecordObject를 호출해야 기획자가 Ctrl + Z로 이전 수치를 복원할 수 있습니다.
  2. 비선택 상태 렌더링 처리 (DrawGizmo): OnSceneGUI는 컴포넌트가 위치한 오브젝트가 선택되어 있을 때만 실행됩니다. 선택되지 않은 상태에서도 수치를 가볍게 확인해야 한다면 DrawGizmo 어트리뷰트나 OnDrawGizmosSelected를 조합하여 렌더링 비용을 최소화합니다.
  3. 빌드 포함 방지: 커스텀 에디터 스크립트는 프로젝트의 Editor 폴더 내부 또는 #if UNITY_EDITOR 전처리기 블록 내에 위치시켜 독립 빌드 실행 파일에 에디터 릴리즈 코드가 포함되지 않도록 주의해야 합니다.

마무리

기획자를 위한 커스텀 에디터 시각화 툴은 개발 초기에는 다소 수공이 들어가는 작업처럼 보이지만 프로젝트 전체 수치 튜닝 및 밸런싱 단계에서 수치 검증 시간을 비약적으로 단축시킵니다. 씬 뷰 기반의 가시적 핸들과 와이어프레임 렌더링을 적극적으로 도입하면 팀 내 기획자와 개발자 간의 커뮤니케이션 오버헤드를 대폭 줄일 수 있습니다.

#Unity#CustomEditor#SceneView#EditorScripting#GameTooling

계속 읽어보기

이런 글은 어떠세요?

< Back to Logs