在游戏中加入第三方的开发调试库,但不想默认打包进游戏,只在不同打包选项时,才进行附加上去,然后在游戏里进行动态加载。
不能使用反射的方式。这里使用的是 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);
}