Unity3D Editor 编辑器扩展实战 脚本编译完成后设置回调函数

环境:Unity2017.2 语言:C#

总起:

今天同事在做自动化的工具,需要在脚本编译完成之后回调一个函数。我在Google上找到UnityEditor.Callbacks.DidReloadScripts这个标签可以在编译完成后,Unity自动帮忙回调。

但是这样很麻烦,可不可以像是主动设置一个函数名称,等编译完成之后进行回调呢?

通过EditorPrefs对需要回调函数名的存储,我大体上完成了以上的想法。

代码:

将以下代码放到Editor文件夹下:

// CompilingFinishedCallback.cs
using System;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;

public static class CompilingFinishedCallback
{
    private static string TmpMethodNamesKey = "CompilingFinishedCallback_TmpMethodNames";

    public static void Set<T>(string methodName, string arg = null)
    {
        var type = typeof(T);
        string methoedName = type.FullName + "." + methodName + "(" + arg + ")";
        AddTmpMethodName(methoedName);
    }

    static string[] GetTmpMethodNameArr()
    {
        return GetTmpMethodNames().Split(';').Where(value=>value != null && value.Trim() != "").ToArray();
    }

    static void AddTmpMethodName(string value)
    {
        SetTmpMethodNames(GetTmpMethodNames() + ";" + value);
    }

    static string GetTmpMethodNames()
    {
        if (EditorPrefs.HasKey(TmpMethodNamesKey))
            return EditorPrefs.GetString(TmpMethodNamesKey);
        return "";
    }

    static void SetTmpMethodNames(string value)
    {
        EditorPrefs.SetString(TmpMethodNamesKey, value);
    }

    [UnityEditor.Callbacks.DidReloadScripts]
    private static void OnScriptsReloaded()
    {
        var methods = GetTmpMethodNameArr();
        foreach (var method in methods)
        {
            var pointIndex = method.LastIndexOf(".");
            var left = method.LastIndexOf("(");
            var right = method.LastIndexOf(")");
            string className = method.Substring(0, pointIndex);
            string methodName = method.Substring(pointIndex + 1, left - pointIndex - 1);
            string argName = method.Substring(left + 1, right - left - 1);
            Type type = Type.GetType(className);
            if (type == null)
            {
                Debug.LogError("type == null");
                continue;
            }
            var method1 = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, new Type[] { }, null);
            var method2 = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
            if (method1 == null && method2 == null)
            {
                Debug.LogError("method1 == null && method2 == null");
                continue;
            }
            if (method1 != null && argName.Trim() == "")
                method1.Invoke(null, null);
            if (method2 != null && argName.Trim() != "")
                method2.Invoke(null, new object[] {argName});
        }
        SetTmpMethodNames("");
    }
}

思路比较简单,就是把函数名存起来,等回调的时候,通过反射进行调用。

新建一个Test来试试效果(放在Editor文件夹下):

// Test.cs
using UnityEditor;
using UnityEngine;
public class Test
{

    [MenuItem("Tool/test")]
    public static void Start()
    {
        CompilingFinishedCallback.Set<Test>("Log");
        CompilingFinishedCallback.Set<Test>("Log", "arg");
    }

    private static void Log()
    {
        Debug.Log("log");
    }

    private static void Log(string arg)
    {
        Debug.Log(arg);
    }
}

首先点击菜单栏的Tool/test按钮,再随便改动一下脚本触发编译,最终效果:



猜你喜欢

转载自blog.csdn.net/u012632851/article/details/80891472