본문 바로가기

개발/Unity

[Unity] 간단한 hierarchy 커스텀

728x90
반응형

회사에서 hierarchy 정리를 하다가 시각적으로 구분하고 싶어졌다...!

그래서 간단하게 hierarchy를 커스텀한코드와 그 과정을 포스팅한다.

누군가에게 조금이라도 도움이 될 수 있기를 바라며...


1. 설계💡

우선 내가 어떻게 커스텀하고 사용할 것인지에 대해 간단(⚠️진짜 간단함)하게 설계를 했다.

  • 원하는 기능 
    • Hierarchy의 시각적 구분 → 기존의 단일 색상과 구분되는 header 기능
    • Header를 자유롭게 추가, 삭제, 수정 할 수 있음
  • 기능 구현을 위한 설계
    • Header data → struct 
      • 구별을 위한 Type 생성 → Enum
      • Color
      • 보여질 Text
    • Header datas → scriptable object

이 정도로 간단하게 설계를 해두고 바로 코드 작성에 들어갔다!


2. 구현 🛠️

우선 header data 구조체와 그것을 list로 저장할 scriptable object를 구현했다.

[CreateAssetMenu(fileName = "HierarchyHeaderData", menuName = "Custom Hierarchy/Header Data")]
public class HierarchyHeaderData : ScriptableObject {
    [System.Serializable]
    public struct HeaderInfo {
        public HEADER_TYPE type;
        public string text;
        public Color color;
    }

    public List<HeaderInfo> HeaderInfos = new();
}

public enum HEADER_TYPE {
    CUBE,
    SPHERE,
    CAPSULE
}

이러면 추가, 수정, 삭제도 용이하며 저장까지 간단하게 사용이 가능하다!

이 data를 이용하여 editor를 그려줄 스크립트도 작성~

using UnityEditor;
using UnityEngine;

[InitializeOnLoad]
public class CustomHierarchy {
    private static HierarchyHeaderData _hierarchyHeaderData;

    static CustomHierarchy() {
        EditorApplication.hierarchyWindowItemOnGUI += HandleHierarchyWindowItemOnGUI;
        _hierarchyHeaderData = AssetDatabase.LoadAssetAtPath<HierarchyHeaderData>("Assets/Data/HierarchyHeaderData.asset");
    }

    private static void HandleHierarchyWindowItemOnGUI(int instanceID, Rect selectionRect) {
        var gameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;

        if (gameObject == null) {
            return;
        }

        var headerRect = new Rect(selectionRect.x, selectionRect.y, selectionRect.width, EditorGUIUtility.singleLineHeight);

        foreach (var headerInfo in _hierarchyHeaderData.HeaderInfos) {
            if (!gameObject.name.Equals(headerInfo.type.ToString())) {
                continue;
            }
            
            EditorGUI.DrawRect(headerRect, headerInfo.color);
            EditorGUI.LabelField(headerRect, headerInfo.text, EditorStyles.whiteBoldLabel);
            break;
        }
    }
}

최종 구현된 코드가 짧고 간단해서 설명 몇 줄만 적자면...

  • Header data가 변경(추가, 수정, 삭제) 될 때마다 반영 될 수 있도록 [InitializeOnLoad] attribute 추가 참고
  • HierarchyWindow의 OnGUI delegate에 커스텀 메서드 연결 참고
  • AssetDatabase.LoadAssetAtPath 함수를 사용하여 header data를 가져옵니다. 참고
  • instanceID값으로 hierarchy에 있는 게임 오브젝트를 가져옵니다.
  • 게임 오브젝트의 이름이 header data의 type와 비교하여 같으면 배경 색상을 변경하고 보여질 텍스트로 변경합니다.

3. 작동 테스트 🕹️

scriptable object에 원하는 header data를 추가!

Type과 똑같은 이름의 게임 오브젝트를 만들면 적용되는 모습.

게임 오브젝트를 만들고 이름을 변경해도 적용된다.

정보를 변경한 후에 저장을 하면 hierarchy에 바로 적용되는 모습을 확인 할 수 있다.

내가 설계했던 기능이 잘 구현된 것을 확인 완료!

이렇게 깔끔하게 정리할 수 있다!


형형색색의 필기도구를 가득 채워 필통 들고 다니던 나에게는 흥미로운 코딩이었다.

역시 나는 결과물이 눈으로 다이나믹하게 보이는 것이 재밌다!

깃 레포를 하나 만들고 기능을 조금씩 추가해봐야겠다.

에셋 스토어에 무료로 배포할 수 있는 퀄리티가 될 때까지~

728x90
반응형