본문 바로가기
개발/Unity

유니티 - 2차원 배열 디버깅 : 커스텀 에디터로 인스펙터 수정하기 (Custom Editors)

by 피로물든딸기 2022. 6. 19.
반응형

Unity 전체 링크

 

2차원 배열 디버깅

 

(1) 2차원 배열 인스펙터에 보여주기 (2D Array in the Inspector)
(2) 커스텀 에디터로 인스펙터 수정하기 (Inspector with Custom Editors)
(3) 에디터 윈도우에서 실시간으로 2차원 배열 디버깅하기 (EditorWindow)
(4) 에디터 윈도우에서 블럭의 위치 Mapping 하기 (EditorWindow)


커스텀 에디터3 x 3 배열을 아래와 같이 인스펙터에 보여주도록 하자.

2차원 배열이 정돈되어 있어 디버깅하기 더 쉽다.

 

참고로 이전 글에서는 3 x 3 배열이 아래와 같이 보였다.


직렬화(Serializable)했던 코드는 지우고 아래의 int[,]에서 다시 시작한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Cube : MonoBehaviour
{
    public int[,] array = new int[3, 3];
}

 

2차원 배열의 값을 실시간으로 보기 위해 아래와 같이 수정한다.

변수 a, b, c를 선언하고 각각 Mouse Down/Drag/Up일 때 값을 1씩 증가시키자.

그리고 array[3,3]에 Cube의 postion.xyz, rotation.xyz, abc에 값을 할당하자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Cube : MonoBehaviour
{
    public int[,] array = new int[3, 3];

    int a, b, c;

    void OnMouseDown()
    {
        a++;
    }

    void OnMouseDrag()
    {
        b++;
    }

    void OnMouseUp()
    {
        c++;
    }

    void Update()
    {
        array[0, 0] = (int)this.transform.position.x;
        array[0, 1] = (int)this.transform.position.y;
        array[0, 2] = (int)this.transform.position.z;

        array[1, 0] = (int)this.transform.rotation.eulerAngles.x;
        array[1, 1] = (int)this.transform.rotation.eulerAngles.y;
        array[1, 2] = (int)this.transform.rotation.eulerAngles.z;

        array[2, 0] = a;
        array[2, 1] = b;
        array[2, 2] = c;
    }
}

이제 CubeEditor.cs를 아래와 같이 만든다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(Cube))]
public class CubeEditor : Editor
{
    Cube cube;
    int[,] debug2d;

    void OnEnable()
    {
        cube = target as Cube;
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        EditorGUILayout.LabelField("2차원 배열");

        debug2d = new int[3, 3];
        debug2d = cube.array.Clone() as int[,];

        for (int i = 0; i < 3; i++)
        {
            EditorGUILayout.BeginHorizontal();
            for (int k = 0; k < 3; k++)
                debug2d[i, k] = EditorGUILayout.IntField(debug2d[i, k]);
            EditorGUILayout.EndHorizontal();
        }
    }
}

 

그러면 Cube Inspector에 아래와 같은 모습을 볼 수 있다.

 

코드 설명

 

커스텀 에디터를 사용하기 위해서는 MonoBehaviour가 아니라 Editor를 상속 받아야 한다.

그리고 [CustomEditor(typeof(Cube))]를 선언해서 Cube 스크립트의 에디터를 고친다는 것을 유니티에게 알린다.

 

Cube 스크립트에 접근할 cube 변수를 선언하고 OnEnable에서 할당한다.

debug2d는 Cube 스크립트에 있는 2차원 배열이다.

    Cube cube;
    int[,] debug2d;

    void OnEnable()
    {
        cube = target as Cube;
    }

 

OnInspectorGUI를 오버라이딩해서 인스펙터를 그린다.

base.OnInspectorGUI()로 기존의 인스펙터를 그대로 그린 후, 추가로 인스펙터를 그렸다.

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        debug2d = new int[3, 3];
        debug2d = cube.array.Clone() as int[,];

        EditorGUILayout.LabelField("2차원 배열");

        for (int i = 0; i < 3; i++)
        {
            EditorGUILayout.BeginHorizontal();
            for (int k = 0; k < 3; k++)
                debug2d[i, k] = EditorGUILayout.IntField(debug2d[i, k]);
            EditorGUILayout.EndHorizontal();
        }
    }

 

LabelField는 제목을 만든다.

 

debug2d를 Clone으로 복사한다.

그리고 이중 루프를 돌면서 debug2d[i, k]에 해당하는 IntFiled를 만든다.

EditorGUILayout.BeginHorizontal / EndHorizontal로 배열을 정리할 수 있다.

    debug2d = new int[3, 3];
    debug2d = cube.array.Clone() as int[,];

    for (int i = 0; i < 3; i++)
    {
        EditorGUILayout.BeginHorizontal();
        for (int k = 0; k < 3; k++)
            debug2d[i, k] = EditorGUILayout.IntField(debug2d[i, k]);
        EditorGUILayout.EndHorizontal();
    }

 

BeginHorizontal / EndHorizontal이 없으면 아래와 같이 일렬로 보이게 된다.

 


이제 게임을 실행한 후, 블럭의 위치를 움직이고 돌려보자.

 

Position과 Rotation의 정수 부분이 2차원 배열의 값에 잘 들어가는 것을 알 수 있다.

 

그러나 오브젝트에 마우스를 Down/Drag/Up할 경우에는 아무 반응이 없다.

그러다가 Inspector에 마우스를 가져가면 a, b, c의 값이 갱신된다.

 

원인은 아래의 링크에 답변되어 있다.

https://answers.unity.com/questions/330518/refreshing-custom-inspector-window-while-playing.html

 

Refreshing custom Inspector window while playing - Unity Answers

 

answers.unity.com

 

직렬화된 속성만 커스텀 에디터가 갱신(redraw, refresh)되기 때문이다.

따라서 a, b, c를 SerializeField로 선언하면 된다.

    [SerializeField]
    int a, b, c;

 

하지만 SerializeField에 의해 불필요하게 변수가 보인다.

 

HideInInspector를 추가하면 원래대로 돌아간다.

    [SerializeField][HideInInspector]
    int a, b, c;

 

이제 마우스 이벤트에도 a, b, c 값이 즉시 갱신된다.

 

전체 코드는 아래와 같다.

 

Cube.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Cube : MonoBehaviour
{
    public int[,] array = new int[3, 3];

    [SerializeField][HideInInspector]
    int a, b, c;

    void OnMouseDown()
    {
        a++;
    }

    void OnMouseDrag()
    {
        b++;
    }

    void OnMouseUp()
    {
        c++;
    }

    void Update()
    {
        array[0, 0] = (int)this.transform.position.x;
        array[0, 1] = (int)this.transform.position.y;
        array[0, 2] = (int)this.transform.position.z;

        array[1, 0] = (int)this.transform.rotation.eulerAngles.x;
        array[1, 1] = (int)this.transform.rotation.eulerAngles.y;
        array[1, 2] = (int)this.transform.rotation.eulerAngles.z;

        array[2, 0] = a;
        array[2, 1] = b;
        array[2, 2] = c;
    }
}

 

CubeEditor.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(Cube))]
public class CubeEditor : Editor
{
    Cube cube;
    int[,] debug2d;

    void OnEnable()
    {
        cube = target as Cube;
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        EditorGUILayout.LabelField("2차원 배열");

        debug2d = new int[3, 3];
        debug2d = cube.array.Clone() as int[,];

        for (int i = 0; i < 3; i++)
        {
            EditorGUILayout.BeginHorizontal();
            for (int k = 0; k < 3; k++)
                debug2d[i, k] = EditorGUILayout.IntField(debug2d[i, k]);
            EditorGUILayout.EndHorizontal();
        }
    }
}

 

이제 Inspector에서 2차원 배열을 편하게 볼 수 있게 되었다.

하지만 하이어라키(Scene)에서 큐브를 선택해야하는 단점이 있다.

이런 경우는 에디터 윈도우로 새로운 창을 하나 만드는 것이 편리하다.


(1) 2차원 배열 인스펙터에 보여주기 (2D Array in the Inspector)
(2) 커스텀 에디터로 인스펙터 수정하기 (Inspector with Custom Editors)
(3) 에디터 윈도우에서 실시간으로 2차원 배열 디버깅하기 (EditorWindow)
(4) 에디터 윈도우에서 블럭의 위치 Mapping 하기 (EditorWindow)

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글