# 유니티3D 기존 NGUI Legacy 컴포넌트를 특정 컴포넌트로 교체하는 기능 ( 테스트중에 있음. ) └→Unity3D/2D

  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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
using UnityEngine;
using System.Collections.Generic;
using UnityEditor;
using System.IO;

// NGUI 라이브러리의 경우
// UIButton 컴포넌트는 UIButtonColor 을 상속받는다.
// UIButtonColor에는 tweenTarget 변수가 있으며, 이 변수가 tweening을 할 대상 오브젝트를 가진다.
// 근데, UIButtonColor.OnInit 메소드에 Unity 버전 4.6, 4.3, 4.5등에 대해 tweenTarget에 Light 컴포넌트가 없으면
// tweenTarget을 null로 할당하는 코드가 있다. 우선 이부분을 주석처리하고 하면 에디터상에서 변경한 버튼컴포넌트 프리팹이
// 씬 화면에 로딩되어도 정상적으로 tweenTarget레퍼런스가 끊기지 않는다.

public class LegacyButtonChanger : Editor
{
private static UIButtonMessage[] legacyUIButtonsMsgs;
private static UIEventTrigger[] legacyUIEventTriggers;

[MenuItem("LegacyButtonChanger/ChangeLegacyButtons")]
public static void ChangeLegacyButtons()
{
Debug.Log("<color=green><b>[Changer_Logging]</b></color>Start Log legacy buttons");
string[] filesFolderPath = Directory.GetFiles("Assets/Prefabs/Lobby/");

// 주어진 파일 폴더경로에서 .prefab 확장의 파일들을 검색한다.
// 해당 파일에 child로 속한 파일들은 얻을 수 없으므로 해당 파일을 root로 하여
// Legacy한 컴포넌트들을 가져온다.
foreach (var p in filesFolderPath)
{
if (Path.GetExtension(p).Equals(".prefab"))
{
GameObject root = AssetDatabase.LoadAssetAtPath(p, typeof(Object)) as GameObject;
if (root == null) Debug.Log("Loaded Asset is NULL");
else
{
ExtractLegacyBtns(root);
ChangeBtnComponent();
//EditorUtility.SetDirty(root);
}
}
}
Debug.Log("<color=green><b>[Changer_Logging]</b></color>Finish Log legacy buttons");
}

private static void ExtractLegacyBtns(GameObject root)
{
legacyUIButtonsMsgs = root.GetComponentsInChildren<UIButtonMessage>();
legacyUIEventTriggers = root.GetComponentsInChildren<UIEventTrigger>();
}
private static void ChangeBtnComponent()
{
// UIButtonMessages..
if (legacyUIButtonsMsgs != null)
{
foreach (var msgComp in legacyUIButtonsMsgs)
{
string targetFuncName = msgComp.functionName;
if (msgComp.target == null)
{
Debug.Log(string.Format(""));
continue;
}
if(targetFuncName == null)
{
Debug.Log(string.Format(""));
continue;
}
if(targetFuncName == "")
{
Debug.Log(string.Format(""));
continue;
}

MonoBehaviour[] targetMonoComponents = msgComp.target.GetComponents<MonoBehaviour>();
if (targetMonoComponents != null)
{
foreach (var targetMonoComp in targetMonoComponents)
{
if (targetMonoComp == null)
{
Debug.Log("Target의 컴포넌트가 Missing 이거나 Null 입니다.");
continue;
}

System.Type scriptType = targetMonoComp.GetType();
if (scriptType.GetMethod(targetFuncName) != null)
{
Debug.Log(string.Format("{0} msgComponent :: {1} is, type--> {2}"
, msgComp.name, targetMonoComp.name, targetMonoComp.GetType()));

GameObject toBeAttachedObj = msgComp.gameObject;
// 타겟의 모노비헤이비어와 메소드이름을 주어 생성하면
// 이벤트델리게이트 클래스 안에서 해당 메소드를 리플렉션하여 파라미터가 필요한지 아닌지를 확인한다.
//
EventDelegate ed = new EventDelegate(targetMonoComp, targetFuncName);
EventDelegate.Parameter param = new EventDelegate.Parameter();
// 파라미터로, 새로운 UIButton 컴포턴트가 붙어야할 오브젝트를 할당해준다.
param.obj = toBeAttachedObj;
// 추출한 타겟의 메소드에서 파라미터를 요구한다면.
if(ed.parameters != null)
{
ed.parameters[0] = param;
}
else // 추출한 타겟의 메소드에서는 파라미터가 없다.
{
// 파라미터를 할당해 줄 필요가 없다.
}
AddUIButtonComp(toBeAttachedObj, ed);
RemoveUIButtonMessage(toBeAttachedObj);
break;
}
else
{
// GetType().GetMethod() 리플렉션에서 메소드를 구해오는건 public만 가능.
// 실패한다면 해당 메소드 접근자는 private 이다.
// 실패한 경우, 해당 메소드가 어느 스크립트에 존재하는지 로그를 남겨야한다.
Debug.Log(string.Format("<color=red><b>[Changer_Alert]</b></color> <b>@Private Accesser Find@"
+"</b> scriptName : {0}, methodName :{1}",
scriptType.Name, targetFuncName));
}
}
}
}
}

// UIEventTriggers..
if (legacyUIEventTriggers != null)
{
foreach (var trigger in legacyUIEventTriggers)
{
Debug.Log(string.Format("attached {0} prefab's parent : {1}, :: {2} is trigger, {3} (OnClick..) ",
trigger.gameObject, trigger.gameObject.transform.parent, trigger.name, trigger.onClick));
GameObject toBeAttachedObj = trigger.gameObject;
AddUIButtonComp(toBeAttachedObj, trigger.onClick);
RemoveUIEventTrigger(toBeAttachedObj);
}
}
}

private static void AddUIButtonComp(GameObject toBeAttachedObj, EventDelegate onClickEvent)
{
UIButton uiButtonComp = toBeAttachedObj.GetComponent<UIButton>();
if (uiButtonComp != null)
{
bool isExist = uiButtonComp.onClick.Exists((other) => {
return other.methodName.Equals(onClickEvent.methodName);
});
if (isExist == false)
{
uiButtonComp.onClick.Add(onClickEvent);
}
// onClick list에 동일한 이벤트가 있던 없던, tween target은 설정해준다.
uiButtonComp.tweenTarget = toBeAttachedObj;
}
else
{
UIButton addedComponent = toBeAttachedObj.AddComponent<UIButton>();
addedComponent.onClick.Add(onClickEvent);
addedComponent.tweenTarget = toBeAttachedObj;
}
}
private static void AddUIButtonComp(GameObject toBeAttachedObj, List<EventDelegate> onClickEvents)
{
UIButton uiButtonComp = toBeAttachedObj.GetComponent<UIButton>();
if (uiButtonComp != null)
{
uiButtonComp.onClick = onClickEvents;
uiButtonComp.tweenTarget = toBeAttachedObj;
}
else
{
UIButton addedComponent = toBeAttachedObj.AddComponent<UIButton>();
addedComponent.onClick = onClickEvents;
addedComponent.tweenTarget = toBeAttachedObj;
}
}

private static void RemoveUIEventTrigger(GameObject obj)
{
if (obj.GetComponent<UIEventTrigger>() != null)
DestroyImmediate(obj.GetComponent<UIEventTrigger>(), true);
}
private static void RemoveUIButtonMessage(GameObject obj)
{
if (obj.GetComponent<UIButtonMessage>() != null)
DestroyImmediate(obj.GetComponent<UIButtonMessage>(), true);
}


}