Version: 2019.3
프로퍼티 드로어
트리 뷰

커스텀 에디터

애플리케이션 개발을 가속화하려면 자주 사용하는 컴포넌트에 대한 커스텀 에디터를 만드십시오. 이 페이지에서는 단순한 스크립트를 생성하여 게임 오브젝트가 항상 특정 지점을 바라보도록 만드는 방법을 설명합니다.

  1. C# 스크립트를 만들고 이름을 "“LookAtPoint”라고 지정합니다.
  2. 스크립트를 열고 콘텐츠를 아래 코드로 교체합니다.
  3. 스크립트를 씬의 게임 오브젝트에 연결합니다.
//C# Example (LookAtPoint.cs)
using UnityEngine;
public class LookAtPoint : MonoBehaviour
{
    public Vector3 lookAtPoint = Vector3.zero;

    void Update()
    {
        transform.LookAt(lookAtPoint);
    }
}

Play 모드를 시작하면 스크립트를 연결한 게임 오브젝트가 이제 “Look At Point” 프로퍼티로 설정한 좌표를 향합니다. 에디터 스크립트를 작성하는 경우 애플리케이션이 실행되지 않을 때 편집 모드에서 스크립트가 실행되도록 만들면 유용할 때가 많습니다. 이렇게 하려면 아래와 같이 클래스에 ExecuteInEditMode 속성을 추가하십시오.

//C# Example (LookAtPoint.cs)
using UnityEngine;
[ExecuteInEditMode]
public class LookAtPoint : MonoBehaviour
{
    public Vector3 lookAtPoint = Vector3.zero;

    void Update()
    {
        transform.LookAt(lookAtPoint);
    }
}

이제 에디터에서 게임 오브젝트를 움직이거나 인스펙터에서 “Look At Point” 값을 변경하면 게임 오브젝트가 회전을 업데이트하여 월드 공간의 타겟 지점을 바라봅니다.

커스텀 에디터 생성

위의 예에는 편집 모드 중에 간단한 스크립트가 실행되도록 할 수 있는 방법이 나와 있지만, 이 방법만으로는 에디터 툴을 직접 만들 수 없습니다. 다음 단계에서는 방금 작성한 스크립트를 위한 Custom Editor 를 만듭니다.

Unity에서 스크립트를 작성하는 경우 기본적으로 MonoBehaviour에서 상속하기 때문에 이 컴포넌트는 게임 오브젝트에 연결이 가능합니다. 컴포넌트를 게임 오브젝트에 배치하면 모든 public 변수(정수, 플로트, 문자열 등)를 확인하고 편집하는 데 사용할 수 있는 기본 인터페이스가 인스펙터에 표시됩니다.

LookAtPoint 컴포넌트의 인스펙터는 기본적으로 다음과 같은 모습입니다.

공용 Vector3 필드가 있는 기본 인스펙터
공용 Vector3 필드가 있는 기본 인스펙터

커스텀 에디터는 이 디폴트 레이아웃을 사용자가 선택하는 에디터 컨트롤로 대체하는 별도의 스크립트입니다.

LookAtPoint 스크립트에 대한 커스텀 에디터를 생성하려면 다음 단계를 따르십시오.

  1. 새로운 C# 스크립트를 만들고 이름을 “LookAtPointEditor”라고 지정합니다.
  2. 스크립트를 열고 콘텐츠를 아래 코드로 교체합니다.
//C# Example (LookAtPointEditor.cs)
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(LookAtPoint))]
[CanEditMultipleObjects]
public class LookAtPointEditor : Editor 
{
    SerializedProperty lookAtPoint;
    
    void OnEnable()
    {
        lookAtPoint = serializedObject.FindProperty("lookAtPoint");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        EditorGUILayout.PropertyField(lookAtPoint);
        serializedObject.ApplyModifiedProperties();
    }
}

이 클래스는 Editor에서 상속되어야 합니다. CustomEditor 속성은 어떤 컴포넌트를 위한 에디터로 동작해야 하는지 Unity에 알립니다. CanEditMultipleObjects 속성은 사용자가 이 에디터로 여러 오브젝트를 선택하고 모두 동시에 변경할 수 있음을 Unity에 알립니다.

Unity는 인스펙터에 에디터를 표시할 때마다 OnInspectorGUI의 코드를 실행합니다. 여기에 아무 GUI 코드나 넣어도 OnGUI와 동일한 방식으로 동작하지만, 인스펙터 내에서 실행됩니다. 에디터는 검사 중인 게임 오브젝트에 액세스하기 위해 사용할 수 있는 타겟 프로퍼티를 정의합니다.

LookAtPoint 컴포넌트의 인스펙터는 새 에디터에서 다음과 같은 모습입니다.

이는 기존과 매우 유사한 모습입니다. (단, 에디터 스크립트가 표시할 인스펙터 코드를 추가하지 않으므로 “Script” 필드는 이제 존재하지 않습니다.)

하지만 이제는 인스펙터가 에디터 스크립트에 표시되는 방식을 제어할 수 있기 때문에 원하는 코드를 사용하여 인스펙터 필드를 레이아웃하고 값을 조정하거나 그래픽스 또는 다른 시각적 요소를 표시할 수도 있습니다. 실질적으로 터레인 시스템 및 애니메이션 임포트 설정 등 훨씬 복잡한 인스펙터를 포함한 Unity 에디터 내에 나타나는 모든 인스펙터는 커스텀 에디터를 생성하는 동안 액세스하는 동일한 API를 사용해 만들어집니다.

다음은 타겟 포인트가 게임 오브젝트 위에 있는지 아래에 있는지 나타내는 메시지를 표시하기 위해 에디터 스크립트를 확장하는 간단한 예입니다.

//C# Example (LookAtPointEditor.cs)
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(LookAtPoint))]
[CanEditMultipleObjects]
public class LookAtPointEditor : Editor
{
    SerializedProperty lookAtPoint;

    void OnEnable()
    {
        lookAtPoint = serializedObject.FindProperty("lookAtPoint");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        EditorGUILayout.PropertyField(lookAtPoint);
        serializedObject.ApplyModifiedProperties();
        if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y)
        {
            EditorGUILayout.LabelField("(Above this object)");
        }
        if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y)
        {
            EditorGUILayout.LabelField("(Below this object)");
        }
    }
}

LookAtPoint 컴포넌트의 인스펙터는 다음과 같은 모습이며, 메시지는 타겟 지점이 게임 오브젝트의 위 또는 아래에 있는지 알려줍니다.

모든 IMGUI 커맨드에 완전히 액세스하여 에디터 창 안에서 카메라를 사용하여 씬을 렌더링하는 등 모든 인터페이스 타입을 드로우할 수 있습니다.

씬 뷰 추가 코드

씬 뷰에 코드를 더 추가할 수 있습니다. 이렇게 하려면 커스텀 에디터에서 OnSceneGUI를 구현하십시오.

OnSceneGUI는 씬 뷰에서 실행된다는 점을 제외하고 OnInspectorGUI와 동일하게 작동합니다. 원하는 편집 컨트롤을 직접 만들기 위해 Handles 클래스에 정의된 함수를 사용할 수 있습니다. 이 클래스의 모든 함수는 3D 씬 뷰에서 동작하도록 설계되었습니다.

//C# Example (LookAtPointEditor.cs)
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(LookAtPoint))]
[CanEditMultipleObjects]
public class LookAtPointEditor : Editor
{
    SerializedProperty lookAtPoint;

    void OnEnable()
    {
        lookAtPoint = serializedObject.FindProperty("lookAtPoint");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        EditorGUILayout.PropertyField(lookAtPoint);
        if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y)
        {
            EditorGUILayout.LabelField("(Above this object)");
        }
        if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y)
        {
            EditorGUILayout.LabelField("(Below this object)");
        }
        
            
        serializedObject.ApplyModifiedProperties();
    }

    public void OnSceneGUI()
    {
        var t = (target as LookAtPoint);

        EditorGUI.BeginChangeCheck();
        Vector3 pos = Handles.PositionHandle(t.lookAtPoint, Quaternion.identity);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(target, "Move point");
            t.lookAtPoint = pos;
            t.Update();
        }
    }
}

2D GUI 오브젝트(GUI 또는 EditorGUI)를 추가하려면 Handles.BeginGUI() 및 Handles.EndGUI() 대상 호출에 래핑해야 합니다.

프로퍼티 드로어
트리 뷰