이번 시간에는 유니티 에디터의 인터페이스를 사용자 친화적으로 더 깔끔하고 보기 쉽게 커스텀해보겠습니다.
이렇게 에디터를 커스텀하는 이유는 작업자인 저는 물론이고 기획자 및 그래픽 아티스트까지 유니티 프로젝트를 확인하기 쉽게 하기위함입니다. 유니티의 강점이 무엇이겠습니까? 바로 협업툴이라는 것이죠!
혼자할 때도 좋지만 개발팀이 다 함께 작업하면 더 좋은 에디터가 바로 유니티입니다. 시작해보죠!
저는 지난 시간에 함께 만들었던 Lotto 프로젝트를 이용해서 진행해볼게요.
여러분들은 지금 하고계신 프로젝트나 새로운 프로젝트를 만드셔도 상관없습니다.
우선 새폴더를 만드시고 Editor로 변경합니다.
Editor라고 명명한 이 폴더는 특수한 기능을 담당하게 됩니다.
폴더 안의 스크립트들은 런타임 스크립트가 아닌, 에디터 스크립트로 간주되며 빌드 시 추가되지 않습니다.
우선 스크립트를 새로 만들고 여러분이 구별할 수 있는 이름으로 수정해주세요.
저는 EasyHierarchy로 수정하였습니다.
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
internal static class EasyHierarchy
{
private const int ROW_HEIGHT = 16;
private const int OFFSET_Y = -4;
private static readonly Color COLOR = new Color(0, 0, 0, 0.08f);
static EasyHierarchy()
{
EditorApplication.hierarchyWindowItemOnGUI += OnGUI;
}
private static void OnGUI(int instanceID, Rect rect)
{
var index = (int)(rect.y + OFFSET_Y) / ROW_HEIGHT;
if (index % 2 == 0) return;
var xMax = rect.xMax;
rect.x = 32;
rect.xMax = xMax + 16;
EditorGUI.DrawRect(rect, COLOR);
}
}
이후에 스크립트 안의 내용을 싹 다 지워준 후 위의 내용을 붙여넣기 해주시고 저장 후 에디터로 돌아와봅시다.
차이점이 보이시나요???
스크립트를 추가하기 전에는 하이어라키 창이 단색으로 이루어졌었다면 스크립트 추가 후에는 한 줄마다 조금 더 진한 색과 옅은 색이 반복되어 게임오브젝트들을 구별하기 쉽게 해줍니다.
지금은 하이어라키 위에 올려진 오브젝트들의 수가 얼마 안 되지만 나중에 프로젝트 규모가 커진다면 하이어라키가 지저분해 원하는 오브젝트를 바로 찾기 어려울 수 있습니다.
이번에는 하이어라키창과 마찬가지로 프로젝트탭 또한 같은 처리를 해주겠습니다.
역시 스크립트를 만든 후 이름을 수정해주세요. 저는 EasyProject로 하였습니다.
using UnityEditor;
using UnityEngine;
public static class EasyProject
{
[InitializeOnLoadMethod]
private static void Example()
{
EditorApplication.projectWindowItemOnGUI += OnGUI;
}
private static void OnGUI(string guid, Rect selectionRect)
{
var index = (int)(selectionRect.y - 4) / 16;
if (index % 2 == 0)
{
return;
}
var pos = selectionRect;
pos.x = 0;
pos.xMax = selectionRect.xMax;
var color = GUI.color;
GUI.color = new Color(0, 0, 0, 0.2f);
GUI.Box(pos, string.Empty);
GUI.color = color;
}
}
프로젝트 탭은 조금 더 쉬운 구별이 가능하겠네요.
이로써 하이어라키와 프로젝트탭을 커스터마이징하였습니다. 아직 끝나지 않았습니다! 계속 따라오세요.
이번에도 스크립트를 추가한 뒤에 ShowComponents라고 명명해주세요.
using System.Linq;
using UnityEditor;
using UnityEngine;
public static class ShowComponents
{
private static readonly Color mDisabledColor = new Color(1, 1, 1, 0.5f);
private const int WIDTH = 16;
private const int HEIGHT = 16;
[InitializeOnLoadMethod]
private static void Example()
{
EditorApplication.hierarchyWindowItemOnGUI += OnGUI;
}
private static void OnGUI(int instanceID, Rect selectionRect)
{
var go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
if (go == null)
{
return;
}
var pos = selectionRect;
pos.x = pos.xMax - WIDTH;
pos.width = WIDTH;
pos.height = HEIGHT;
var components = go
.GetComponents<Component>()
.Where(c => c != null)
.Where(c => !(c is Transform))
.Reverse();
var current = Event.current;
foreach (var c in components)
{
Texture image = AssetPreview.GetMiniThumbnail(c);
if (image == null && c is MonoBehaviour)
{
var ms = MonoScript.FromMonoBehaviour(c as MonoBehaviour);
var path = AssetDatabase.GetAssetPath(ms);
image = AssetDatabase.GetCachedIcon(path);
}
if (image == null)
{
continue;
}
if (current.type == EventType.MouseDown &&
pos.Contains(current.mousePosition))
{
//c.SetEnable(!c.IsEnabled());
}
var color = GUI.color;
GUI.color = c.IsEnabled() ? Color.white : mDisabledColor;
GUI.DrawTexture(pos, image, ScaleMode.ScaleToFit);
GUI.color = color;
pos.x -= pos.width;
}
}
public static bool IsEnabled(this Component self)
{
if (self == null)
{
return true;
}
var type = self.GetType();
var property = type.GetProperty("enabled", typeof(bool));
if (property == null)
{
return true;
}
return (bool)property.GetValue(self, null);
}
public static void SetEnable(this Component self, bool isEnabled)
{
if (self == null)
{
return;
}
var type = self.GetType();
var property = type.GetProperty("enabled", typeof(bool));
if (property == null)
{
return;
}
property.SetValue(self, isEnabled, null);
}
}
스크립트 안의 내용들을 위의 코드로 수정해줍니다.
이번에 추가한 스크립트는 차이점이 한 눈에 들어오시죠?
바로 게임오브젝트에 추가된 컴포넌트들이 게임오브젝트의 이름 옆에 보이게 됩니다.
컴포넌트들을 마우스 클릭으로 끄고 켜는 기능도 할 수 있지만 직접 사용해보니 마우스 더블 클릭과 혼용되는 커멘드이기도 하고 실수로 컴포넌트들을 꺼거나 켜는 일이 발생하여 해당 기능을 삭제한 상태입니다.
해당 기능을 사용하고 싶으신 분들은 스크립트의 내용 중 위의 부분을 찾아 주석을 제거하시면 됩니다.
마지막으로 한 가지만 더 추가하겠습니다.
스크립트를 추가 후 ShowWarningObjects 로 명명해주세요.
using System.Linq;
using UnityEditor;
using UnityEngine;
public static class ShowWarningObjects
{
private const int WIDTH = 80;
[InitializeOnLoadMethod]
private static void Example()
{
EditorApplication.hierarchyWindowItemOnGUI += OnGUI;
}
private static void OnGUI(int instanceID, Rect selectionRect)
{
var go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
if (go == null)
{
return;
}
var isWarning = go
.GetComponents<MonoBehaviour>()
.Any(c => c == null);
if (!isWarning)
{
return;
}
var pos = selectionRect;
pos.x = pos.xMax - WIDTH;
pos.width = WIDTH;
GUI.Label(pos, "!");
}
}
스크립트의 내용을 싹 다 지운 뒤에 위의 내용으로 수정합니다.
이번에 추가한 커스텀 에디터 스크립트는 어떠한 변화도 보이지 않습니다.
물론 지금은 말이죠.
하지만 스크립트의 연결이 끊어진다면 어떻게 될까요?
하이어라키창의 게임오브젝트 이름의 옆에 ! 로 경고를 표시해줍니다.
스크립트의 연결이 끊어지는 경우는 보통은 작업자의 실수로 인해 나타나죠.
협업을 할 때도 유니티를 잘 모르는 분들이 이것저것 건드리게 된다면 종종 발생합니다.
이 때 실행을 하면 오류와 함께 실행이 안 되거나 실행 중에 특정 부분에서 오류와 함께 동작을 하지않게 됩니다.
이 전에 미리 !로 표시를 해주어 무언가 오류가 있으니 수정을 하라 라는 경고를 보내는 것이죠.
오늘은 사용자로 하여금 더 쉽고 편안하게 유니티를 다룰 수 있도록 에디터를 커스터마이징해보았습니다.
제가 소개한 기능은 총 네 가지이지만 사실 에디터 커스터마이징은 셀 수도 없이 많이 존재합니다.
여러분이 필요한 특정 기능이 있다면 검색을 해보시거나 직접 만드실 수도 있겠죠.
다음 시간에도 유용한 팁을 가지고 여러분께 소개해드리겠습니다.
오늘도 따라오시느라 고생하셨습니다 :D