Unity_未完成品SendMessageUpwards
关于Invoke的一些方法可以看我上篇博客-->>使用反射完成一个Invoke(其实我感觉应该是SendMessage)
https://blog.****.net/MikuLingSSS/article/details/83422814
============================================代码================================================
因为就是那上篇的代码进行的扩展,所以这些代码会连着上篇的代码,
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Reflection;
//SendMessageUpward<-OR->BroadcastMessage使用多线程,先在主线程中找到所有本级物体以及父级物体上面的所有Mono组件,压入一个parent列表
//之后新建一个线程,在里面进行递归,如果找到方法就把我们找到的数据暂时的压进一个dict<className,list<methodName>>中,在parent为空的时候,我们就可以遍历这个dict来进行数据的操作
//感觉这个想法可行
//(上面这段话是我上篇博客最后留下的,但是实现没有用到线程,因为我测试了一下代码的延迟,发现根本没有用到线程的必要,所以pass(其实还是因为有几个难点懒得去思考 = = ,比如join,比如并发查询,执行))
/*
* 实施可能性:
一:遍历所有父级物体继承了Mono组建的类,压入列表
二:对列表进行查询,比对,执行
三:退出子线程,进入主线程中进行对查找到数据的操作
* 缺点:
感觉速度和延迟会撑不住,时间太长了->
*/
public static class InvokeExtension
{
#region SendMessageUpward
/// <summary>
/// 查找到所有的继承了Mono的自身以及父级物体组建
/// </summary>
/// <param name="transform"></param>
/// <param 需要反射的方法名="method_name"></param>
/// <param 参数和参数类型的列表="obj"></param>
/// <returns></returns>
public static object SelfInvokeUpward(this Transform transform, string method_name, params object[] obj)
{
List<Type> class_name_list = new List<Type>();
Transform trans = transform;
Type[] type_list = new Type[obj.Length / 2];
object[] obj_list = new object[obj.Length / 2];
for (int i = 0; i < obj.Length; i++)
{
if (i % 2 == 0)
{
type_list[i / 2] = (Type)obj[i];
continue;
}
obj_list[i / 2] = obj[i];
}
while (trans.parent != null) // 一步步递归到最上层,并获取这里面继承了Mono的脚本
{
trans = trans.parent;
if (trans.parent == null)
{
Component[] thisComponent = trans.GetComponents(typeof(MonoBehaviour));
class_name_list.AddClass_Type(thisComponent);
}
for (int l = 0; l < trans.childCount; l++)
{
Component[] childComponent = trans.GetChild(l).GetComponents(typeof(MonoBehaviour));
class_name_list.AddClass_Type(childComponent);
}
}
List<SaveClass_Method> temp = class_name_list.SelectClassData(method_name, obj_list, type_list);
List<object> return_obj_list = new List<object>();
for (int i = 0; i < temp.Count; i++)
{
return_obj_list.Add(temp[i]._class_name.GetMethod(method_name, type_list).Invoke(temp[i]._instance, obj_list));
}
return return_obj_list;
}
/// <summary>
/// 通过Type返回对象的instance typeof(Class_name)
/// </summary>
/// <param name="sel"></param>
/// <param 我们需要找到的方法名="method_name"></param>
/// <param 参数列表="obj"></param>
/// <param 参数类型列表="type"></param>
/// <returns></returns>
private static List<SaveClass_Method> SelectClassData(this List<Type> sel, string method_name, object[] obj, Type[] type)
{
List<SaveClass_Method> t = new List<SaveClass_Method>();
for (int i = 0; i < sel.Count; i++)
{
foreach (MethodInfo item in sel[i].GetMethods())
{
if (item.Name == method_name && item.GetParameters().Length == obj.Length && IsConsistent(item.GetParameters(), type))
{
//这个结构体在最下面
SaveClass_Method save_class = new SaveClass_Method();
save_class._instance = GetInstance(sel[i]);
save_class._class_name = sel[i];
t.Add(save_class);
}
}
}
return t;
}
/// <summary>
/// 获得当前组建的所有继承Mono的类
/// </summary>
private static void AddClass_Type(this List<Type> list, Component[] com)
{
for (int i = 0; i < com.Length; i++)
{
list.Add(Type.GetType(com[i].GetType().ToString()));
}
}
#endregion
#region Invoke 以下是上篇博客代码
public static object SelfInvoke(this Transform transform, string methodName, params object[] params_obj)
{
object obj = null;
Component[] component = transform.GetComponents(typeof(MonoBehaviour));
for (int i = 0; i < component.Length; i++)
{
Type class_name = Type.GetType(component[i].GetType().ToString());
Iteration(class_name, methodName, ref obj, params_obj);
}
return obj;
}
private static void Iteration(Type class_name, string methodName, ref object obj, params object[] params_obj)
{
Type[] type;
object[] params_obj_obj;
if (params_obj.Length == 0 || params_obj == null)
{
type = new Type[] { };
params_obj_obj = new object[] { };
}
else
{
type = new Type[params_obj.Length / 2];
params_obj_obj = new object[params_obj.Length / 2];
for (int i = 0; i < params_obj.Length; i++)
{
if (i % 2 == 0)
{
type[i / 2] = (Type)params_obj[i];
continue;
}
params_obj_obj[i / 2] = params_obj[i];
}
}
foreach (MethodInfo item in class_name.GetMethods())
{
if (item.Name == methodName && item.GetParameters().Length == type.Length && IsConsistent(item.GetParameters(), type))
{
object instance = GetInstance(class_name);
obj = class_name.GetMethod(methodName, type).Invoke(instance, params_obj_obj);
}
}
}
private static bool IsConsistent(ParameterInfo[] info, Type[] type) // 失败
{
for (int i = 0; i < type.Length; i++)
{
if (info[i].ParameterType != type[i])
{
return false;
}
}
return true;
}
private static object GetInstance(Type t)
{
return Activator.CreateInstance(t);
}
#endregion
#region Font Size And Color
// 下面都是富文本颜色,就不说了
public static string Str_Red(this string str, int size = 12)
{
return "<color=#ff0000><size=" + size + ">" + str + "</size></color>";
}
public static string Str_Green(this string str, int size = 12)
{
return "<color=#00ff00><size=" + size + ">" + str + "</size></color>";
}
public static string Str_Rand(this string str, int size = 12)
{
string color_16 = "";
for (int i = 0; i < 3; i++)
{
color_16 += Convert.ToString(UnityEngine.Random.Range(0, 255), 16);
}
return "<color=#" + color_16 + "><size=" + size + ">" + str + "</size></color>";
}
public static string Str_Blue(this string str, int size = 12)
{
return "<color=#0000ff><size=" + size + ">" + str + "</size></color>";
}
#endregion
}
// 这是我们需要保存的结构
public struct SaveClass_Method
{
public object _instance;
public Type _class_name;
}
调用代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Run_Test_Scripts : MonoBehaviour
{
public GameObject game_obj;
void Start()
{
transform.SelfInvokeUpward("Test", typeof(string), "this is sibada!!!");
transform.SelfInvokeUpward("Test", typeof(int), 133, typeof(int), 144, typeof(string), "-QAQ-");
transform.SelfInvokeUpward("Test", typeof(GameObject), game_obj);
}
}
其他的类代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Cube_Test_prefab1,2,header代码都一样,不过Cube_Test_prefab_2 多出一个使用GameObject参数的重载
public class Cube_Test_prefab_2 : MonoBehaviour {
public string Name
{
get
{
return typeof(Cube_Test_prefab_3).ToString();
}
}
public void Test(string _str)
{
Debug.Log(Name.Str_Red() + "->(string)->" + _str.ToString().Str_Blue());
}
public void Test(int _int)
{
Debug.Log(Name.Str_Red() + "->(int)->" + _int.ToString().Str_Blue());
}
public void Test(int _int, int _int2, string _str)
{
Debug.Log(Name.Str_Red() + "->(int,int,int)->".Str_Red() + ((_int + _int2) + _str).Str_Blue());
}
// 就是这个重载,
public void Test(GameObject game_obj)
{
Debug.Log(game_obj.name);
game_obj.transform.position = new Vector3(1, 0, 0);
}
}
Unity Scene结构:
运行结果:::
================================================================================================
可以看到,在最后录制的时候,爆出了几个Ctor的错误,这些应该是在CreateInstance的时候出现的,目前不清楚怎么修 = = ,