一开始做项目的时候,涉及NGUI特别多,项目中需要非常多的Button以及和它对应的事件,通常的实现方式都是下面这种情况:
1 private void BtnClickHandler(GameObject go) 2 { 3 switch (go.name) 4 { 5 case "regist": 6 RegistUser(); 7 break; 8 case "forgetPwd": 9 ForGetPassWord(); 10 break; 11 case "submit": 12 DoLogin(); 13 break; 14 case "exit": 15 QuitApp(); 16 break; 17 case "NoRegistLogin": 18 PublicVals.IsRegistUser = false; 19 LoadScene("SeleMode"); 20 break; 21 } 22 }
我吧,很不喜欢这种判断方式,当然这不代表我下面实现的功能,比这个要好或者要方便,只是单纯我个人想去这么实现而已。NGUI的Button自带了一个功能On Click,我有很多同事也用这种方式来实现按钮和事件的关联,我也比较喜欢这个功能,但是我想把所有Button放到一个脚本下管理或者说放到一个Inspector下管理( 什么样的值会被显示在Inspector面板上?已经被序列化,但是没有用HideInInspector标记的值。),去阅读一下NGUI的源代码发现所有这样的事件功能都是通过public List<EventDelegate> onSubmit = new List<EventDelegate>()这样的方式来定义的,通过下面的方法来进行调用的。
public void Submit () { if (NGUITools.GetActive(this)) { mValue = value; if (current == null) { current = this; EventDelegate.Execute(onSubmit); current = null; } SaveToPlayerPrefs(mValue); } }
方法名的获取是通过反射的方式,在EventDelegateEditor这个类中实现的,具体方法如下
1 static public List<Entry> GetMethods (GameObject target) 2 { 3 MonoBehaviour[] comps = target.GetComponents<MonoBehaviour>(); 4 5 List<Entry> list = new List<Entry>(); 6 7 for (int i = 0, imax = comps.Length; i < imax; ++i) 8 { 9 MonoBehaviour mb = comps[i]; 10 if (mb == null) continue; 11 12 MethodInfo[] methods = mb.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); 13 14 for (int b = 0; b < methods.Length; ++b) 15 { 16 MethodInfo mi = methods[b]; 17 18 if (mi.ReturnType == typeof(void)) 19 { 20 string name = mi.Name; 21 if (name == "Invoke") continue; 22 if (name == "InvokeRepeating") continue; 23 if (name == "CancelInvoke") continue; 24 if (name == "StopCoroutine") continue; 25 if (name == "StopAllCoroutines") continue; 26 if (name == "BroadcastMessage") continue; 27 if (name.StartsWith("SendMessage")) continue; 28 if (name.StartsWith("set_")) continue; 29 30 Entry ent = new Entry(); 31 ent.target = mb; 32 ent.name = mi.Name; 33 list.Add(ent); 34 } 35 } 36 } 37 return list; 38 }
这样我们就获得方法名了,然后通过编辑Inspector来实现想要的界面效果,具体代码如下:
public override void OnInspectorGUI() { monoscript.Update(); EditorGUILayout.PropertyField(connectionPool); if (connectionPool.isExpanded) { EditorGUI.indentLevel += 1; EditorGUILayout.PropertyField(connectionPool.FindPropertyRelative("script")); ButtonEvent scripttarget = (ButtonEvent)target; string[] names; string[] tnames={"Please insert script"}; if (scripttarget.connectionPool.script != null) { List<string> temp = GetMethods(scripttarget.connectionPool.script); names = temp.ToArray(); } else { names = null; } SerializedProperty list = connectionPool.FindPropertyRelative("buttonConnection"); EditorGUILayout.PropertyField(list); if (list.isExpanded) { EditorGUI.indentLevel += 1; EditorGUILayout.PropertyField(list.FindPropertyRelative("Array.size")); if (list.arraySize > 0) { for (int i = 0; i < list.arraySize; i++) { SerializedProperty mlist = list.GetArrayElementAtIndex(i); EditorGUILayout.PropertyField(mlist,new GUIContent("BE"+i)); if (mlist.isExpanded) { EditorGUI.indentLevel += 1; EditorGUILayout.PropertyField(mlist.FindPropertyRelative("button")); if (scripttarget.connectionPool.buttonConnection.Length >= list.arraySize) { if (names != null) { scripttarget.connectionPool.buttonConnection[i].indexNum = EditorGUILayout.Popup("Method", scripttarget.connectionPool.buttonConnection[i].indexNum, names); scripttarget.connectionPool.buttonConnection[i].methodName = names[scripttarget.connectionPool.buttonConnection[i].indexNum]; } else { scripttarget.connectionPool.buttonConnection[i].indexNum = EditorGUILayout.Popup("Method", scripttarget.connectionPool.buttonConnection[i].indexNum, tnames); scripttarget.connectionPool.buttonConnection[i].methodName = tnames[scripttarget.connectionPool.buttonConnection[i].indexNum]; } } else { if (names != null) EditorGUILayout.Popup("Method", 0, names); else EditorGUILayout.Popup("Method", 0, tnames); } //EditorGUILayout.PropertyField(mlist.FindPropertyRelative("methodName")); EditorGUI.indentLevel -= 1; } } } } } monoscript.ApplyModifiedProperties(); }
最后实现的效果如图
将事件代码拖入Script,在ButtonConnection中Button拖入对应button,method里面选择方法后,点击Button调用事件。
这个功能看起来有些本末倒置,只是在我个人强迫症的驱使下完成的,谢谢。
时间: 2024-10-07 23:21:04