【Unity3D】NativePlugin开发方法工具推荐

前提

  推荐一个Native C++开发工具。
  默认Unity Native插件开发,C#用[DllImport("dll名称")]标注,存在一个问题是,如果想要重新编译Plugin,需要先将UnityEditor关闭,不然原有的dll还被占用,无法将新编译的dll动态库更新到Unity工程。
  一种修复方法是,使用LoadLibrary手动加载、管理dll而不是让Unity管理,已有工具UnityNativeTool能做到这一点。

使用方法

  1. 到relase中下载UnityPackage导入到项目中。
  2. 场景中加一个空物体挂在DllManipulatorScript用来配置。
  看一些常用选项:

①Enable in Edit Mode

  不需要游戏运行也能让工具生效

②Only Assembly-CSharp(-Editor)

  默认只在Assembly-CSharpAssembly-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,现在被工具拦截后,会替换上述pattern,{assets}会替换成你的Assets的全路径,{name}会替换你的dll名称,这个例子里,整体会替换成Assets/Plugins/__MyPlugin.dll,也因此你需要将编译好的dll定义成这个名字,然后拷贝到这个路径下。
  你也可以根据你的喜好自定义路径,例如写成{assets}/Plugins/mocks/__{name}.dll等等。

  添加好上述选项后,Mocked Dlls检测到生效的dll和路径,会在Inspector中显示出来,当需要更新Plugin时,点Inspector的Unload all DLLs即可(或者Alt+D快捷键)。


  这些dll就会被解除占用,此时更新dll文件,下次extern函数调用时,就会是更新过后的方法。

配合使用方式

  拷贝dll依旧是一步手动操作,可以生成构建时,自动拷贝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工程生成时也能照常执行:

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)

  经过上述配置后,更新插件我只需要Alt+D,生成dll两步即可更新dll,而无需重启编辑器。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容