일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 벡터
- Cell Shader
- 프로그래밍 기초
- 개인 바이트
- Windows Build
- ASW(Application SpaceWarp)
- Three(Two) Tone Shading
- Virtual Byte
- Toon Shader
- 작업 집합
- 3d
- working set
- 메모리 누수
- ColorGradingLutPass
- C언어
- URP
- 가상 바이트
- URP로 변경
- Rim Light
- Cartoon Rendering
- AppSW
- Specular
- 게임 수학
- Cell Look
- OculusMotionVectorPass
- VR
- Private Bytes
- Today
- Total
WinCNT
Unity의 EditorWindow를 한 번 알아보자 그 두번째! 이번엔 Reflection과 Action으로 Method를 실행해보자! 본문
Unity의 EditorWindow를 한 번 알아보자 그 두번째! 이번엔 Reflection과 Action으로 Method를 실행해보자!
WinCNT_SSS 2024. 3. 28. 09:49서론
저번 글에 이어지는 EditorWindow 내용이다
https://wincnt-shim.tistory.com/406
테스트를 위해 선택한 GameObject를 Count하는 메소드 작성
의미 없는 메소드를 만들어도 슬플 뿐이니 무엇인가 기능을 하나 만들어서 테스트해보자
이번 대상은 선택한 GameObject를 Count하는 메소드이다(최적화는 나중에 생각하자…)
#region Selected GameObject Vertex-Count
private void DrawSelectionVertexCounter()
{
_selectionGameObjects = Selection.gameObjects.ToList();
EditorGUILayout.BeginVertical(GUI.skin.GetStyle("HelpBox"));
EditorGUILayout.LabelField("Selected GameObject Vertex-Count", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
{
EditorGUILayout.IntField("Skin", CountMeshVertex(GetAllSkinnedMeshRenderers(_selectionGameObjects)));
EditorGUILayout.IntField("mesh", CountMeshVertex(GetAllMeshFilter(_selectionGameObjects)));
}
EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
Repaint();
}
#endregion
#region Private Methods
private List<SkinnedMeshRenderer> GetAllSkinnedMeshRenderers(List<GameObject> rootGameObject)
{
var meshes = new List<SkinnedMeshRenderer>();
foreach (var gameObject in rootGameObject)
meshes.AddRange(gameObject.GetComponentsInChildren<SkinnedMeshRenderer>(true));
return meshes.OrderByDescending(x => x.sharedMesh.vertexCount).ToList();
}
private List<MeshFilter> GetAllMeshFilter(List<GameObject> rootGameObject)
{
var meshes = new List<MeshFilter>();
foreach (var gameObject in rootGameObject)
meshes.AddRange(gameObject.GetComponentsInChildren<MeshFilter>(true));
return meshes.OrderByDescending(x => x.sharedMesh.vertexCount).ToList();
}
private static int CountMeshVertex(List<SkinnedMeshRenderer> list)
{
return list
.Where(i => i is not null)
.Where(i => i.gameObject.activeInHierarchy)
.Sum(i => i.sharedMesh.vertices.Length);
}
private static int CountMeshVertex(List<MeshFilter> list)
{
return list
.Where(i => i is not null)
.Where(i => i.gameObject.activeInHierarchy)
.Sum(i => i.sharedMesh.vertices.Length);
}
#endregion
위의 메소드들을 만들고 OnGUI에서 실행하도록 추가하자!
private List<GameObject> _selectionGameObjects = new List<GameObject>();
private void OnGUI()
{
DrawSelectionVertexCounter();
//...생략...
}
짜잔~!
Custom Attribute 만들기
다음으로 Reflection로 찾을 Attribute를 만들었다
예전과 같이 PropertyAttribute를 사용하고 싶었지만 이번엔 Method가 대상이라 사용할 수 없었다
어쩔 수 없이 Attribute를 상속받은 OnInspectorGUIAttribute를 만들었다
using System;
public class OnInspectorGUIAttribute : Attribute { }
그리고 DrawSelectionVertexCounter() 위에 장착!
[OnInspectorGUI]
private void DrawSelectionVertexCounter()
{
// 생략
}
Reflection로 Custom Attribute 찾기!
전에 구현했던 GetTargetProperty의 응용
이번에는 GetMethods()로 MethodInfo를 찾는다는 게 차이점이다
그리고 찾은 메소드는 나중에 실행하기 위해 Delegate.CreateDelegate로 Action를 만들어서 리스트에 따로 보관해뒀다
private List<Action> targetMethodList = new List<Action>();
SerializedObject targetObject;
private void OnEnable()
{
targetObject = new SerializedObject(this);
targetObject.Update();
var iterator = targetObject.GetIterator();
while (iterator.NextVisible(true))
{
GetTargetMethod(targetObject, iterator);
// ...생략...
}
targetObject.ApplyModifiedProperties();
// ...생략...
}
private void GetTargetMethod(SerializedObject serializedObject, SerializedProperty property)
{
try
{
var type = serializedObject.targetObject.GetType();
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (methods.Length != 0)
{
foreach (var method in methods)
{
var attributes = method.GetCustomAttributes(true);
foreach (var attr in attributes)
{
if (attr.GetType() == typeof(OnInspectorGUIAttribute))
{
Action action = (Action) Delegate.CreateDelegate(typeof(Action), serializedObject.targetObject, method);
targetMethodList.Add(action);
}
}
}
}
// duplicates remove
targetMethodList = targetMethodList.Distinct().ToList();
}
catch (Exception e)
{
Debug.Log(e);
throw;
}
}
나머지는 실행해줄 뿐!
이제 targetMethodList에 보관한 메소드를 실행시키면 끝!
private List<GameObject> _selectionGameObjects = new List<GameObject>();
private void OnGUI()
{
// DrawSelectionVertexCounter();
if (targetObject != null)
{
targetObject.Update();
foreach (var method in targetMethodList)
{
method.Invoke();
}
// ...생략...
targetObject.ApplyModifiedProperties();
}
//...생략...
}
짜잔
결과
다른 메소드에 붙여도 잘 되나 실험해보자
[OnInspectorGUI]
private void DrawSelectionVertexCounter()
{
_selectionGameObjects = Selection.gameObjects.ToList();
EditorGUILayout.BeginVertical(GUI.skin.GetStyle("HelpBox"));
EditorGUILayout.LabelField("Selected GameObject Vertex-Count", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
{
EditorGUILayout.IntField("Skin", CountMeshVertex(GetAllSkinnedMeshRenderers(_selectionGameObjects)));
EditorGUILayout.IntField("mesh", CountMeshVertex(GetAllMeshFilter(_selectionGameObjects)));
}
EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
Repaint();
}
[OnInspectorGUI]
private void DrawSelectionVertexCounter2()
{
// DrawSelectionVertexCounter과 동일
}
[OnInspectorGUI]
private void DrawSelectionVertexCounter3()
{
// DrawSelectionVertexCounter과 동일
}
문제 없이 잘 동작한다!
마무리
필자는 필요한 어트리뷰트만 추가해서 대응했지만 Odin 같은 에셋은 이미 설계부터 제대로 해놨겠지…문득 새삼 Odin이 대단하게 느껴지네
앞으로 또 추가해야 할 일이 생겨도 이제는 이 방식으로 할지 모르겠다구현이 너무 귀찮음
참고 사이트
이번엔 딱히 딱 맞는 참고 사이트는 없었다
'Unity > Unity 관련' 카테고리의 다른 글
Volume의 Bloom에서 추가 속성(Addtional Properties)인 Downscale, Max Iterations를 표시하고 최적화하기! (0) | 2024.04.01 |
---|---|
Unity의 EditorWindow를 한 번 알아보자 그 첫번째! 덤으로 Reflection과 PropertyDrawer로 List 요소만 표시해보자! (0) | 2024.03.25 |
Unity에서 커스텀 ShaderGUI를 구현해보자! 그 두번째 (0) | 2024.02.09 |
UniTask를 인스톨하고 살짝 사용해봤다! (0) | 2023.11.30 |
Unity 2022.2부터 Navigation이 AI Navigation로 바뀌었다길래 사용해봤다 (0) | 2023.11.14 |