利用反射 便捷开发 unity 扩展

很多时候 我们想运行一个调用一个函数 只有 在Unity 运行的时候 点击 button触发 或者 等待 那个函数 调用的上下文 触发的时候 才能 调用那个函数 , 如果调用的 场景很苛刻 ,那么 我们改如何 自己调用呢 ,显然 我们可以 直接 创建一个button 来主动触发 咱们自己的函数,但是这样还是有些麻烦 ,于是 我想到了 一种 利用 Unity 编辑器 扩展 +反射,通过类名 ,和函数名 来调用自己想触发的函数 下面 上代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System;
using System.Reflection;

public class strget
{
    public string s;
    public string name;
}
public class floatger
{
    public float f;

    public int ind => (int)f;
    public uint uid => (uint)f;
    public ushort usd => (ushort)f;
    public short shd => (short)f;
   public byte byd => (byte)f;

    public Type targetType;    
    public string name="";
}
public class boolget
{
    public bool b;
    public string name = "";
}
[CustomEditor(typeof(ReflectionEditor))]
public class ReflectionEditor : EditorWindow
{
    [MenuItem("MyTools/Reflection")]
    public static void startReflectionEditor()
    {
        EditorWindow window = EditorWindow.GetWindow(typeof(ReflectionEditor));
    }

    string ClassDesc = "ClassName";
    string ClassName;

    string MethodDesc = "MethodName";
    string MethodName;

    List<object> Params = new List<object>();

    List<object> SendData => ConversionData(Params);

    public string address = "";
    private void OnGUI()
    {
        drawContent(ClassDesc, ref ClassName);
        drawContent(MethodDesc, ref MethodName);
        DrawButton();
        DrawParams();
    }
    void DrawButton()
    {
        EditorGUILayout.BeginHorizontal();
        startBtn();
        AddStrParamBtn();
        AddFloatParamBtn();
        autoParamButton();
        resetBtn();
        EditorGUILayout.EndHorizontal();
    }

    void AddStrParamBtn()
    {
        if (GUILayout.Button("AddStr"))
        {
            Params.Add(new strget());

        }
    }
    void AddFloatParamBtn()
    {
        if (GUILayout.Button("Addfloat"))
        {
            Params.Add(new floatger());
        }
    }

    void autoParam()
    {
       
        if (mod == null)
            return;
        Params.Clear();
       
        foreach (var param in mod.GetParameters())
        {
            Debug.LogError(param.ParameterType);
            if (hasType(param.ParameterType, typeof(float), typeof(int), typeof(uint), typeof(byte), typeof(ulong), typeof(short), typeof(ushort)))
            {
                Params.Add(new floatger() { name = param.Name, targetType = param.ParameterType });
            }
            else if (param.ParameterType == typeof(string))
            {
                Params.Add(new strget() { name = param.Name });
            }
            else if (hasType(param.ParameterType, typeof(bool)))
            {
                Params.Add(new boolget() { name = param.Name });
            }
            else
            {
                Params.Add(null);
            }
        }  
    }
    void DrawParams()
    {
        for (byte i = 0; i < Params.Count; i++)
        {

            if (Params[i] is strget strget)
            {
                drawContent($"参数:{strget.name}{i}", ref strget.s);
            }
            else if (Params[i] is floatger floatger)
            {
                drawfloatContent($"参数:{floatger.name}{i}", ref floatger.f);
            }
            else if (Params[i] is boolget bl)
            {
                drawBoolContent($"参数:{bl.name}{i}", ref bl.b);
            }
        }
    }
    bool hasType(Type targetT, params Type[] types)
    {
        bool have = false;
        for (int i = 0; i < types.Length; i++)
        {
            if (targetT == types[i])
                return true;
        }
        return false;
    }


    void autoParamButton()
    {
        if (GUILayout.Button("autoParam"))
        {
            if (!tryGetMod(out mod))
            {
                trygetSelectMod();
            };
            autoParam();
        }
    }
    void resetBtn()
    {
        if (GUILayout.Button("Rest"))
        {
            Params.Clear();
        }
    }
    MethodInfo mod;
    void startBtn()
    {
        if (GUILayout.Button("运行"))
        {
            mod = null;
            if (Selection.gameObjects.IsNullOrEmpty())
            {
                Debug.LogError("没有选择的对象");
            }
            if (!tryGetMod(out mod))
            {
               var v = trygetSelectMod();
                if (v ==null)
                    return;
                if (Params.Count == 0 || Params == null)
                {
                    mod.Invoke(v, null);
                }
                else
                    mod.Invoke(v, SendData.ToArray());
            }
            else
            {
                if (Params.Count == 0 || Params == null)
                {
                    mod.Invoke(null, null);
                }
                else
                    mod.Invoke(null, SendData.ToArray());
            }    
        }
    }

    MonoBehaviour trygetSelectMod()
    {
        if (Selection.gameObjects.IsNullOrEmpty())
        {
            Debug.LogError("没有当前选择的物体");
            return null;
        }
        var target = Selection.gameObjects[0];

        var v = target.GetComponent(ClassName) as MonoBehaviour;

        if (v == null)
        {
            Debug.LogError($"选择的对象{v.name}没有继承于MonBehaviour");
            return null;
        }
        var t = v.GetType();
        mod = t.GetMethod(MethodName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);
        return v;
    }



    bool tryGetMod(out MethodInfo mod)
    {
        var tAsb = Assembly.Load("Assembly-CSharp");
        Type type = tAsb.GetType(ClassName);
        mod = null;
        if (type == null)
            return false;
        mod = type.GetMethod(MethodName, BindingFlags.Public | BindingFlags.Static );

        return mod != null;
    }


    void drawContent(string desc, ref string content)
    {

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField(desc, GUILayout.Width(100));
        content = EditorGUILayout.TextArea(content);
        EditorGUILayout.EndHorizontal();
    }

    void drawfloatContent(string desc, ref float content)
    {
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField(desc, GUILayout.Width(100));
        content = EditorGUILayout.FloatField(content);
        EditorGUILayout.EndHorizontal();
    }
    void drawBoolContent(string desc, ref bool content)
    {
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField(desc, GUILayout.Width(100));
        content = EditorGUILayout.ToggleLeft(desc,content);
        EditorGUILayout.EndHorizontal();
    }

    List<object> ConversionData(List<object> l)
    {

        if (l.IsNullOrEmpty())
            return null;
        List<object> m_l = new List<object>();
        for (int i = 0; i < l.Count; i++)
        {
            if (l[i] is strget strget)
            {
                m_l.Add(strget.s);
            }
            else if (l[i] is floatger floatger)
            {
                if (istype(typeof(float)))
                {
                    m_l.Add(floatger.f);
                }
                else if (istype(typeof(byte)))
                {
                    m_l.Add(floatger.byd);
                }
                else if (istype(typeof(int)))
                {
                    m_l.Add(floatger.ind);
                }
                else if (istype(typeof(uint)))
                {
                    m_l.Add(floatger.uid);
                }
                else if (istype(typeof(short)))
                {
                    m_l.Add(floatger.shd);
                }
                else if (istype(typeof(ushort)))
                {
                    m_l.Add(floatger.usd);
                }
                bool istype(Type type)
                {
                    return floatger.targetType == type;
                }
            }
            else if (l[i] is boolget boolget)
            {
                m_l.Add(boolget.b);
            }
            else
            {
                m_l.Add(null);
            }
        }
        return m_l;   
    }
}


效果就是 填上类名 和 函数名 就可以调用类里的函数了 ,如果是Unity 里对象的组件自定义 脚本 非静态函数 则需要点击那个对象 在执行就可以了
例子
在这里插入图片描述
在这里插入图片描述
点击运行
在这里插入图片描述
非常滴方便 肯定还有很多提升空间 还请大佬指教

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值