Unity 动态加载第三方开发调试库

目的

在游戏中加入第三方的开发调试库,但不想默认打包进游戏,只在不同打包选项时,才进行附加上去,然后在游戏里进行动态加载。

方法

不能使用反射的方式。这里使用的是 Unity 2018,所以利用Assembly Definition功能在工程里,创建一个辅助插件来进行调用第三方库。

辅助类的代码大致如下:

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Scripting;
#if ENABLE_A_UWA
#if UNITY_IPHONE
using UWAPlatform = UWA.IOS;
#elif UNITY_ANDROID
using UWAPlatform = UWA.Android;
#elif UNITY_STANDALONE_WIN
using UWAPlatform = UWA.Windows;
#else
using UWAPlatform = UWA;
#endif
#endif
 
[assembly: AlwaysLinkAssembly]
 
namespace AAAAAHelper
{
    /// 
    /// 用来动态开启第三方插件,利用【Scripting Define Symbols】
    /// 目前有以下3个宏:
    /// ENABLE_A_UWA
    /// ENABLE_A_REMOTE
    /// ENABLE_A_POCO
    /// 
    [Preserve]
    public class A_Helper : MonoBehaviour
    {
#if !UNITY_EDITOR
        static A_Helper()
        {
            Debug.Log("AAAAAHelper is running static");
            SceneManager.sceneLoaded += OnSceneLoaded;
        }
 
        static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
        {
            SceneManager.sceneLoaded -= OnSceneLoaded;
            new GameObject("AAAAAHelper").AddComponent<A_Helper>();
            Debug.Log("AAAAAHelper is running OnSceneLoaded");
        }
 
        [RuntimeInitializeOnLoadMethod]
        static void OnRuntimeMethodLoad()
        {
            Debug.Log("AAAAAHelper is running0");
        }
#endif
 
        /// 
        /// 在游戏运行时,适当时机,通过物体对象来发送这个消息,启用第三方插件
        /// 
        private void EnableThirdParty()
        {
            Debug.Log("AAAAAHelper is running EnableThirdParty");
            EnableHdgRemoteDebug();
        }

主要是通过宏来控制调用,那么就在打包的时候,进行动态设置所需要的插件宏,以及需要动态将脚本挂到初始场景上,否则会被剔除掉。

    /// 
    /// 设置插件(托管、Native)的平台启用
    /// 
    private static void SetPluginEnable(string dllName, bool isEnable)
    {
        var importers = PluginImporter.GetAllImporters();
        foreach (var importer in importers)
        {
            if (importer.assetPath.EndsWith("/" + dllName, StringComparison.OrdinalIgnoreCase))
            {
                Debug.LogFormat("SetPluginEnable : {0} {1}", isEnable, dllName);
                importer.SetCompatibleWithPlatform(EditorUserBuildSettings.activeBuildTarget, isEnable);
            }
        }
    }

    /// 
    /// 设置宏定义的平台启用
    /// 
    private static void SetDefineSymbolsEnable(string define, bool isEnable)
    {
        BuildTargetGroup curBuildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
        string existSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(curBuildTargetGroup);

        if (isEnable)
        {
            if (!existSymbols.Contains(define))
            {
                PlayerSettings.SetScriptingDefineSymbolsForGroup(curBuildTargetGroup, existSymbols + ";" + define);
            }
        }
        else
        {
            if (existSymbols.Contains(define))
            {
                PlayerSettings.SetScriptingDefineSymbolsForGroup(curBuildTargetGroup, existSymbols.Replace(";" + define, ""));
            }
        }
        Debug.LogFormat("SetDefineSymbolsEnable : {0} {1}", isEnable, define);
    }

    /// 
    /// 设置ASMDEF文件的平台启用
    /// 
    private static void SetAssemblyDefinitionEnable(string assemblyName, bool isEnable)
    {
        var assetPath = UnityEditor.Compilation.CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName);
        if (string.IsNullOrEmpty(assetPath))
        {
            return;
        }
        var asset = AssetDatabase.LoadAssetAtPath<AssemblyDefinitionAsset>(assetPath);
        if (!asset)
        {
            return;
        }

        var platformName = string.Empty;
        if (isEnable)
        {
            var activeBuildTarget = EditorUserBuildSettings.activeBuildTarget;
            var platforms = UnityEditor.Compilation.CompilationPipeline.GetAssemblyDefinitionPlatforms();
            foreach (var definitionPlatform in platforms)
            {
                if (definitionPlatform.BuildTarget == activeBuildTarget)
                {
                    platformName = definitionPlatform.Name;
                    break;
                }
            }
            if (string.IsNullOrEmpty(platformName))
            {
                return;
            }
        }
        else
        {
            platformName = "Editor\",\"WindowsStandalone32";
        }

        var includePlatforms = string.Format("\"includePlatforms\": [\"{0}\"],\n", platformName);
        var data = asset.text;

        var posStart = data.IndexOf("\"includePlatforms\"", StringComparison.Ordinal);
        var posEnd = data.IndexOf("    \"excludePlatforms\"", StringComparison.Ordinal);
        var newData = string.Format("{0}{1}{2}", data.Substring(0, posStart), includePlatforms, data.Substring(posEnd));

        File.WriteAllText(assetPath, newData);
        AssetDatabase.ImportAsset(assetPath);
        Debug.LogFormat("SetAssemblyDefinitionEnable : {0} {1}", isEnable, assemblyName);
    }

    /// 
    /// 对具体场景的具体物体添加另一个Assembly的类型组件
    /// 
    private static void SetSceneGameObjectAddComponentEnable(string scenePath, string goName, string assemblyName, string typeName, bool isEnable)
    {
        var assembly = ArrayUtility.Find(AppDomain.CurrentDomain.GetAssemblies(), a => a.GetName().Name == assemblyName);
        if (assembly == null)
        {
            return;
        }

        var componentType = ArrayUtility.Find(assembly.GetTypes(), t => t.FullName == typeName);
        if (componentType == null)
        {
            return;
        }

        if (!(EditorSceneManager.loadedSceneCount == 1 && SceneManager.GetActiveScene().path == scenePath))
        {
            EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single);
        }
        var scene = SceneManager.GetActiveScene();
        var go = ArrayUtility.Find(scene.GetRootGameObjects(), g => g.name == goName);
        if (!go)
        {
            return;
        }

        if (isEnable)
        {
            go.AddComponent(componentType);
        }
        else
        {
            var comp = go.GetComponent(componentType);
            if (comp)
            {
                UnityEngine.Object.DestroyImmediate(comp);
            }
        }
        Debug.LogFormat("SetSceneGameObjectAddComponentEnable : {0} {1}", isEnable, scenePath);
    }

你可能感兴趣的:(3.3,Unity)