Unity Gizmos와 Handles로 에디터 시각화 구현
Gizmos는 씬 뷰에서 디버그 정보를 시각화하는 도구입니다. Handles는 씬 뷰에서 직접 조작 가능한 UI 요소를 만들어 컴포넌트 값을 인터랙티브하게 편집할 수 있습니다. 두 API 모두 에디터 전용이므로 빌드에 영향을 주지 않습니다.
1. OnDrawGizmos / OnDrawGizmosSelected
섹션 제목: “1. OnDrawGizmos / OnDrawGizmosSelected”using UnityEngine;
public class PatrolAgent : MonoBehaviour{ [SerializeField] private float detectionRadius = 5f; [SerializeField] private float attackRadius = 2f; [SerializeField] private Transform[] waypoints;
// 항상 표시 void OnDrawGizmos() { // 감지 반경 (반투명) Gizmos.color = new Color(1, 1, 0, 0.1f); Gizmos.DrawSphere(transform.position, detectionRadius);
Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(transform.position, detectionRadius);
// 순찰 경로 if (waypoints != null && waypoints.Length > 1) { Gizmos.color = Color.cyan; for (int i = 0; i < waypoints.Length; i++) { if (waypoints[i] == null) continue;
// 포인트 표시 Gizmos.DrawSphere(waypoints[i].position, 0.2f);
// 경로 연결 int next = (i + 1) % waypoints.Length; if (waypoints[next] != null) Gizmos.DrawLine(waypoints[i].position, waypoints[next].position); } } }
// 선택 시만 표시 void OnDrawGizmosSelected() { // 공격 반경 (빨간색) Gizmos.color = new Color(1, 0, 0, 0.3f); Gizmos.DrawSphere(transform.position, attackRadius);
Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, attackRadius);
// 전방 방향 Gizmos.color = Color.blue; Gizmos.DrawRay(transform.position, transform.forward * 3f); }}2. 다양한 Gizmos 도형
섹션 제목: “2. 다양한 Gizmos 도형”void OnDrawGizmos(){ // 구체 Gizmos.DrawSphere(center, radius); Gizmos.DrawWireSphere(center, radius);
// 박스 Gizmos.DrawCube(center, size); Gizmos.DrawWireCube(center, size);
// 선 Gizmos.DrawLine(from, to); Gizmos.DrawRay(origin, direction);
// 메시 Gizmos.DrawMesh(mesh, position, rotation, scale); Gizmos.DrawWireMesh(mesh, position, rotation, scale);
// 아이콘 (Assets/Gizmos/ 폴더에 이미지 배치) Gizmos.DrawIcon(transform.position, "MyIcon.png", allowScaling: true);
// 프러스텀 (카메라 시야각 시각화) Gizmos.DrawFrustum(transform.position, 60f, 100f, 0.1f, 1.77f);
// 행렬 변환 적용 Gizmos.matrix = transform.localToWorldMatrix; Gizmos.DrawWireCube(Vector3.zero, Vector3.one); // 로컬 공간 Gizmos.matrix = Matrix4x4.identity; // 리셋}3. Handles — 드래그 가능한 에디터 핸들
섹션 제목: “3. Handles — 드래그 가능한 에디터 핸들”#if UNITY_EDITORusing UnityEditor;
[CustomEditor(typeof(LightSource))]public class LightSourceEditor : Editor{ void OnSceneGUI() { var light = (LightSource)target;
// 드래그 가능한 반경 핸들 EditorGUI.BeginChangeCheck();
float newRadius = Handles.RadiusHandle( Quaternion.identity, light.transform.position, light.radius);
if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(light, "Change Light Radius"); light.radius = newRadius; }
// 레이블 표시 Handles.Label( light.transform.position + Vector3.up * (light.radius + 0.5f), $"반경: {light.radius:F1}m", EditorStyles.boldLabel);
// 색상 원 표시 Handles.color = new Color(1f, 0.8f, 0f, 0.5f); Handles.DrawSolidDisc(light.transform.position, Vector3.up, light.radius); }}#endif4. Handles.PositionHandle — 이동 핸들
섹션 제목: “4. Handles.PositionHandle — 이동 핸들”void OnSceneGUI(){ var target = (WaypointPath)this.target;
for (int i = 0; i < target.points.Count; i++) { EditorGUI.BeginChangeCheck();
Vector3 newPos = Handles.PositionHandle( target.points[i], Quaternion.identity);
if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Move Waypoint"); target.points[i] = newPos; }
// 번호 레이블 Handles.Label(target.points[i] + Vector3.up * 0.3f, $"#{i}"); }
// 경로 연결 Handles.color = Color.green; for (int i = 0; i + 1 < target.points.Count; i++) Handles.DrawLine(target.points[i], target.points[i + 1], 2f);}5. 조건부 컴파일로 빌드에서 제거
섹션 제목: “5. 조건부 컴파일로 빌드에서 제거”public class DebugVisualizer : MonoBehaviour{ [SerializeField] private bool showGizmos = true;
#if UNITY_EDITOR void OnDrawGizmos() { if (!showGizmos) return; DrawDebugInfo(); }
void OnDrawGizmosSelected() { DrawDetailedInfo(); }
void DrawDebugInfo() { Gizmos.color = Color.green; Gizmos.DrawWireSphere(transform.position, 1f); }
void DrawDetailedInfo() { // 선택 시에만 상세 정보 표시 var style = new GUIStyle(); style.normal.textColor = Color.white; Handles.Label(transform.position, $"Position: {transform.position}", style); } #endif}6. 실전 — 스폰 영역 시각화
섹션 제목: “6. 실전 — 스폰 영역 시각화”public class SpawnZone : MonoBehaviour{ [SerializeField] private Vector3 size = Vector3.one * 10f; [SerializeField] private int maxEnemies = 20; [SerializeField] private Color zoneColor = new Color(0, 1, 0, 0.1f);
void OnDrawGizmos() { Gizmos.matrix = transform.localToWorldMatrix;
// 반투명 박스 Gizmos.color = zoneColor; Gizmos.DrawCube(Vector3.zero, size);
// 외곽선 Gizmos.color = zoneColor * 3f; Gizmos.color = new Color(zoneColor.r, zoneColor.g, zoneColor.b, 1f); Gizmos.DrawWireCube(Vector3.zero, size); }
#if UNITY_EDITOR void OnDrawGizmosSelected() { Gizmos.matrix = transform.localToWorldMatrix;
// 스폰 포인트 미리보기 var rng = new System.Random(42); Gizmos.color = Color.red; for (int i = 0; i < Mathf.Min(maxEnemies, 10); i++) { Vector3 point = new Vector3( (float)(rng.NextDouble() - 0.5) * size.x, (float)(rng.NextDouble() - 0.5) * size.y, (float)(rng.NextDouble() - 0.5) * size.z); Gizmos.DrawSphere(point, 0.2f); }
// 정보 레이블 Handles.Label(transform.position, $"스폰 존\n최대 적: {maxEnemies}명\n크기: {size}"); } #endif}| API | 용도 |
|---|---|
Gizmos.DrawWireSphere | 와이어프레임 구체 |
Gizmos.DrawLine | 선 |
Gizmos.matrix | 좌표 변환 적용 |
Handles.PositionHandle | 드래그 이동 핸들 |
Handles.RadiusHandle | 반경 조절 핸들 |
Handles.Label | 씬 뷰 텍스트 |
OnDrawGizmos | 항상 표시 |
OnDrawGizmosSelected | 선택 시만 표시 |