前提
??推薦一個Native C++開發(fā)工具。
??默認Unity Native插件開發(fā),C#用[DllImport("dll名稱")]標注,存在一個問題是,如果想要重新編譯Plugin,需要先將UnityEditor關(guān)閉,不然原有的dll還被占用,無法將新編譯的dll動態(tài)庫更新到Unity工程。
??一種修復方法是,使用LoadLibrary手動加載、管理dll而不是讓Unity管理,已有工具UnityNativeTool能做到這一點。
使用方法
??1. 到relase中下載UnityPackage導入到項目中。
??2. 場景中加一個空物體掛在DllManipulatorScript用來配置。
??看一些常用選項:
①Enable in Edit Mode
??不需要游戲運行也能讓工具生效
②Only Assembly-CSharp(-Editor)
??默認只在Assembly-CSharp、Assembly-CSharp-Editor生效,如果你的Plugin的C#交互接口有自己的asmdef,就需要取消勾選并添加自己的程序集名稱。
??注: 有一個坑,較新版本的編輯器,程序集名稱還有Assembly-CSharp-Editor-firstpass,你可以在Inspector面板添加,也可以去DllManipulator.cs中添加。
③Dll Path pattern
??名稱的匹配模式,默認是{assets}/Plugins/__{name}.dll
??工作方法是這樣:如果你的接口聲明是:
public class MyPluginClass
{
[DllImport("MyPlugin")]
private static extern bool MyPluginFunction(
}
??原本Unity會去尋找MyPlugin.dll,現(xiàn)在被工具攔截后,會替換上述pattern,{assets}會替換成你的Assets的全路徑,{name}會替換你的dll名稱,這個例子里,整體會替換成Assets/Plugins/__MyPlugin.dll,也因此你需要將編譯好的dll定義成這個名字,然后拷貝到這個路徑下。
??你也可以根據(jù)你的喜好自定義路徑,例如寫成{assets}/Plugins/mocks/__{name}.dll等等。
??添加好上述選項后,Mocked Dlls檢測到生效的dll和路徑,會在Inspector中顯示出來,當需要更新Plugin時,點Inspector的Unload all DLLs即可(或者Alt+D快捷鍵)。

??這些dll就會被解除占用,此時更新dll文件,下次extern函數(shù)調(diào)用時,就會是更新過后的方法。
配合使用方式
??拷貝dll依舊是一步手動操作,可以生成構(gòu)建時,自動拷貝dll,例如VS中是項目屬性>生成事件>生成后事件,參考UnityNativeRenderPlugin:
<PostBuildEvent>
<Command>SETLOCAL
if "$(PlatformShortName)" == "x86" (
set TARGET_PLUGIN_PATH=$(SolutionDir)..\..\..\UnityProject\Assets\Plugins\x86
) else (
set TARGET_PLUGIN_PATH=$(SolutionDir)..\..\..\UnityProject\Assets\Plugins\x86_64
)
echo Target Plugin Path is %TARGET_PLUGIN_PATH%
copy /Y "$(TargetPath)" "%TARGET_PLUGIN_PATH%\$(TargetFileName)"
ENDLOCAL
</Command>
</PostBuildEvent>
??我是xmake組織的C++項目,在target中可以加入after_build,這樣xmake導出的VS工程生成時也能照常執(zhí)行:
after_build(function (target)
local target_base_path
if target:is_arch("x86") then
target_base_path = path.join("../GPUDrivenPlayergroundUnityProject/Assets/Plugins/x86")
else
target_base_path = path.join("../GPUDrivenPlayergroundUnityProject/Assets/Plugins/x86_64")
end
local target_plugin_path
if is_mode("debug") then
target_plugin_path = target_base_path
elseif is_mode("release") then
target_plugin_path = path.join(target_base_path, "GPUDrivenPlugin/RenderingPlugin")
end
print("Target Plugin Path is " .. target_plugin_path)
os.mkdir(target_plugin_path)
if is_mode("debug") then
os.cp(target:targetfile(), path.join(target_plugin_path, "__" .. path.filename(target:targetfile())))
elseif is_mode("release") then
os.cp(target:targetfile(), path.join(target_plugin_path, path.filename(target:targetfile())))
end
end)
??經(jīng)過上述配置后,更新插件我只需要Alt+D,生成dll兩步即可更新dll,而無需重啟編輯器。