2026-02-12 15:23:25 +00:00
using UnityEngine ; // 유니티 엔진의 기본 기능을 불러올거에요 -> UnityEngine을
using UnityEditor ; // 유니티 에디터 기능을 사용할거에요 -> UnityEditor를
2026-02-02 08:30:23 +00:00
2026-02-12 15:23:25 +00:00
namespace GameSystems.Optimization.Editor // 에디터 네임스페이스를 정의할거에요 -> GameSystems.Optimization.Editor로
2026-02-02 08:30:23 +00:00
{
2026-02-12 15:23:25 +00:00
[CustomEditor(typeof(PlayerRangeManager))] // 커스텀 에디터 대상을 지정할거에요 -> PlayerRangeManager 클래스로
public sealed class PlayerRangeManagerEditor : UnityEditor . Editor // 클래스를 선언할거에요 -> 에디터 상속을 받는 PlayerRangeManagerEditor를
2026-02-02 08:30:23 +00:00
{
2026-02-12 15:23:25 +00:00
private SerializedProperty _configProperty ; // 변수를 선언할거에요 -> 설정 속성을 연결할 _configProperty를
private SerializedProperty _parentsProperty ; // 변수를 선언할거에요 -> 부모 목록 속성을 연결할 _parentsProperty를
2026-02-02 08:30:23 +00:00
2026-02-12 15:23:25 +00:00
private void OnEnable ( ) // 에디터가 활성화될 때 실행할거에요 -> OnEnable 함수를
2026-02-02 08:30:23 +00:00
{
2026-02-12 15:23:25 +00:00
_configProperty = serializedObject . FindProperty ( "_config" ) ; // 찾을거에요 -> 대상의 "_config" 변수를
2026-02-02 08:30:23 +00:00
// ⭐ [에러 해결] 리스트 이름 '_environmentParents'를 정확히 찾아옵니다.
2026-02-12 15:23:25 +00:00
_parentsProperty = serializedObject . FindProperty ( "_environmentParents" ) ; // 찾을거에요 -> 대상의 "_environmentParents" 변수를
2026-02-02 08:30:23 +00:00
}
2026-02-12 15:23:25 +00:00
public override void OnInspectorGUI ( ) // 인스펙터 화면을 그릴거에요 -> OnInspectorGUI 함수를
2026-02-02 08:30:23 +00:00
{
2026-02-12 15:23:25 +00:00
PlayerRangeManager manager = ( PlayerRangeManager ) target ; // 변수를 설정할거에요 -> 현재 선택된 매니저 객체로
serializedObject . Update ( ) ; // 실행할거에요 -> 객체의 최신 데이터를 불러오기를
2026-02-02 08:30:23 +00:00
// === 헤더 ===
2026-02-12 15:23:25 +00:00
DrawMainHeader ( ) ; // 함수를 실행할거에요 -> 메인 헤더를 그리는
2026-02-02 08:30:23 +00:00
2026-02-12 15:23:25 +00:00
EditorGUILayout . Space ( 5 ) ; // 공간을 줄거에요 -> 5픽셀만큼의 여백을
2026-02-02 08:30:23 +00:00
// === 설정 영역 ===
2026-02-12 15:23:25 +00:00
EditorGUILayout . BeginVertical ( EditorStyles . helpBox ) ; // 수직 영역을 시작할거에요 -> 헬프박스 스타일로
GUILayout . Label ( "필수 설정" , EditorStyles . boldLabel ) ; // 라벨을 표시할거에요 -> "필수 설정"이라는 제목을
EditorGUILayout . PropertyField ( _configProperty ) ; // 그려낼거에요 -> 설정 에셋 입력 필드를
2026-02-02 08:30:23 +00:00
// ⭐ [에러 해결] 리스트를 안전하게 그립니다.
2026-02-12 15:23:25 +00:00
if ( _parentsProperty ! = null ) // 조건이 맞으면 실행할거에요 -> 부모 속성이 유효하다면
2026-02-02 08:30:23 +00:00
{
2026-02-12 15:23:25 +00:00
EditorGUILayout . PropertyField ( _parentsProperty , new GUIContent ( "Environment Parents" ) , true ) ; // 그려낼거에요 -> 자식 요소까지 포함한 리스트 필드를
2026-02-02 08:30:23 +00:00
}
2026-02-12 15:23:25 +00:00
EditorGUILayout . EndVertical ( ) ; // 수직 영역을 종료할거에요
2026-02-02 08:30:23 +00:00
// === 실시간 통계 ===
2026-02-12 15:23:25 +00:00
if ( Application . isPlaying & & manager . IsInitialized ) // 조건이 맞으면 실행할거에요 -> 게임 중이고 초기화되었다면
2026-02-02 08:30:23 +00:00
{
2026-02-12 15:23:25 +00:00
EditorGUILayout . Space ( 5 ) ; // 여백을 줄거에요
EditorGUILayout . BeginVertical ( EditorStyles . helpBox ) ; // 수직 영역을 시작할거에요
GUILayout . Label ( "실시간 통계" , EditorStyles . boldLabel ) ; // 제목을 표시할거에요 -> "실시간 통계"를
EditorGUILayout . LabelField ( "총 오브젝트:" , manager . TotalObjectCount . ToString ( ) ) ; // 텍스트를 표시할거에요 -> 총 개수 정보를
EditorGUILayout . LabelField ( "표시 중:" , manager . VisibleObjectCount . ToString ( ) ) ; // 텍스트를 표시할거에요 -> 현재 표시 개수 정보를
EditorGUILayout . LabelField ( "컬링 효율:" , $"{(manager.CullingEfficiency * 100f):F1}%" ) ; // 텍스트를 표시할거에요 -> 효율 퍼센트 정보를
EditorGUILayout . EndVertical ( ) ; // 수직 영역을 종료할거에요
2026-02-02 08:30:23 +00:00
}
2026-02-12 15:23:25 +00:00
EditorGUILayout . Space ( 5 ) ; // 여백을 줄거에요
2026-02-02 08:30:23 +00:00
// === 컨트롤 버튼 ===
2026-02-12 15:23:25 +00:00
if ( GUILayout . Button ( "🔄 오브젝트 목록 새로고침" , GUILayout . Height ( 30 ) ) ) // 조건이 맞으면 실행할거에요 -> 버튼을 눌렀다면
2026-02-02 08:30:23 +00:00
{
2026-02-12 15:23:25 +00:00
if ( Application . isPlaying ) manager . RefreshObjectList ( ) ; // 실행할거에요 -> 실행 중일 때 목록 갱신 기능을
2026-02-02 08:30:23 +00:00
}
2026-02-12 15:23:25 +00:00
serializedObject . ApplyModifiedProperties ( ) ; // 실행할거에요 -> 변경된 데이터를 실제 객체에 반영하기를
if ( Application . isPlaying ) Repaint ( ) ; // 실행할거에요 -> 실행 중일 때 화면을 다시 그리기를
2026-02-02 08:30:23 +00:00
}
2026-02-12 15:23:25 +00:00
private void DrawMainHeader ( ) // 함수를 선언할거에요 -> 메인 헤더를 그리는 DrawMainHeader를
2026-02-02 08:30:23 +00:00
{
2026-02-12 15:23:25 +00:00
EditorGUILayout . BeginVertical ( EditorStyles . helpBox ) ; // 수직 영역을 시작할거에요
GUILayout . Label ( "Player Range Manager" , new GUIStyle ( EditorStyles . boldLabel ) { fontSize = 14 , alignment = TextAnchor . MiddleCenter } ) ; // 큰 제목을 그릴거에요 -> 중앙 정렬된 스타일로
EditorGUILayout . EndVertical ( ) ; // 수직 영역을 종료할거에요
2026-02-02 08:30:23 +00:00
}
}
}