Unity工程无代码化

简介: Unity工程无代码化目的Unity默认是将代码放入工程,这样容易带来一些问题。代码和资源混合,职能之间容易互相误改。当代码量膨胀到一定程度后,代码的编译时间长到无法忍受。新版的unity支持通过asmdef来将代码分成多个dll工程,有所缓解。

Unity工程无代码化
目的
Unity默认是将代码放入工程,这样容易带来一些问题。

  1. 代码和资源混合,职能之间容易互相误改。
  2. 当代码量膨胀到一定程度后,代码的编译时间长到无法忍受。新版的unity支持通过asmdef来将代码分成多个dll工程,有所缓解。

所以,我们可以将代码全部挪到Unity工程之外,将代码编译成dll,然后把dll以managed plugin的方式放入unity工程。

实现
那么,我们怎么组织代码工程呢。先看下unity的vs tool自动生成的工程格式。

Assembly-Csharp: Scripts下的代码

Assembly-Csharp-Editor: Editor下的代码

Assembly-Csharp-firstpass: PluginsScripts下的代码 (一般还有个Csharp-firstpass-editor的工程,此工程下为Plugins/Editor的代码)

Unity.2D.Spritexx:这个是笔者导入的Sprite2D的package,由于此package为unity内置,实际存放目录在Unity安装目录的 Data/Resources/PackageManager/Builtin下。非内置的在Library/PackagesCache目录下。

查看工程settings

首先需要打开查看权限,visual studio-option-tools for unity-general,将Access to project properties改成True。

具体的compilation symbols很长,这里就不贴出来了。

此时,我们直接将此工程拷贝到项目外面,然后批量修改csproj里的文件路径,右键build,将dll放入原工程,触发unity编译后,会出现很多重复定义的报错,没关系,这是因为dll和工程内的代码重复了。

直接删吗?不急,先备份下工程。

删除代码,报错消失。点play,所有功能消失,一大堆script missing的warning。

原有脚本的meta都被删除了,难怪。没办法,用文本全局替换下guid。

原始脚本的meta 类似这样

而dll内的脚本meta 类似这样

其中fileID为dll的guid,而guid为dll内class的id(class名字不变的情况下,此ID不会变)

批量替换后,点play,一切恢复正常。(此批量替换过程,理论上完全可以自动化)

至此,工作是否已经完成?

没有。

这时候打包,会提示dll reference了 UnityEditor.dll,怎么办呢? 查看project 的编译宏,果然有各种UNITY_EDITOR的宏。

看来需要在打包的时候,单独重新编译dll。

好在visual studio支持命令行打包dll,即msbuild。本地编译runtime的dll,命令行如下

Msbuild xx.csproj /t:Rebuild /p:DefineConstants=a;b;c;…

此处的defienConstants即为编译宏,覆盖了csproj里定义的define。依次将csharp和csharp-plugin编译。(Editor dll暂时忽略)

再次打包,成功。

但是此时 点击编辑器的play,你会发现有些功能发生异常(取决于代码),有些定义找不到了。原因是Editor的dll和Play的dll不兼容了(编译宏不一样)。所以为了编辑器运行正常,又得编译一遍play的dll。

此过程到此,感觉流程已经走通了。然而在发布到项目组正式开发流程之前,还有一些问题需要解决。

问题
代码调试问题
vs调试 managed dll时,需要mdb文件。所以我们在编译dll时,需要手动生成mdb。可以从google上下载一个pdb2mdb,在post build时,自动生成mdb,并将mdb和dll拷贝到unity工程。(隔壁项目组说将pdb和dll放入工程,unity会自动生成mdb,但尝试了n次均失败,遂放弃unity自带的mdb功能)。

编译宏问题
unity编译代码的宏,来自于几个地方:

  1. Build setting defines
  2. asmdef内的定义
  3. unity内部的define(根据buildplayer传入的platform和buildoption来决定)

如果仅靠visual tools生成的工程里的define,显然不太实际。vs tools本身不负责编译dll,工程里的define仅仅为了方便代码编辑和代码自动补全。这部分可以查看 vs tools的源码(已经做成package了),vs tools是根据unity编译出的dll,去自动更新vs工程。而无代码化后的流程 其实是反过来了。

不过,通过查看 visual studio code editor源码,找到unity一个内部的接口

通过此接口,可以获取各个target和option的编译宏

引用依赖问题
Vs tools是将所有可能依赖的dll全部加到reference列表中,多的reference倒是无所谓,最终编译都只会包含真正需要引用的dll。但是ref dll的路径 需要处理下,默认为全路径,但每个人机器上unity安装目录都不一样,所以需要通用化。有两个方法:

  1. 将dll拷贝到工程同级目录,将ref hintpath改成相对路径(不过,在unity升级后,此目录也需要升级,不适合unity需要频繁升级的项目)
  2. 添加环境变量UNITY_PATH,修改csproj,示例如下

csproj的Condition可以很好的解决不同环境下的一致性问题

Include scripts问题
由于涉及到多人协作,我们的csproj没有采取正则include,而是显式的include了每个代码文件,这样产生了两个问题

  1. 所有人都需要提交csproj,而csproj默认是将新加的代码添加至末尾,所以在多人同时新加文件时,很容易产生冲突,而且不能自动resolve,需要手动合并。
  2. 若引入了第三方的package,升级变得繁琐,要逐个检查是否需要include

为了解决这个问题,综合各个方面,决定使用终极方案,即根据代码文件/asmdef以及自定义的一些规范,自动生成csproj,这个过程跟vs tools类似。实现后,开发不再需要提交csproj文件,并且会自动检测代码文件的新增或删除,并自动修改,这样你的visual studio会自动提示reload(是不是跟原始的工作流程很像了?)。这个自动生成的过程,可以参考visual studio editor package代码,此处就不再做详细展开。

Burst compile问题
Unity2019提供了burst功能,这个burst过程是在打包阶段发生的,它会自动扫描unity自动生成的dll(即Csharpt-xxx系列)内的代码,然后进行burst。但是此时我们的代码都在plugins下的dll里,所以扫描不到。此时需要修改burst package相关的代码,具体如何修改就不贴了,很简单。

总结

踩了不少坑,也对unity的编译环节有所了解。切换过来后,感觉是一种新的体验,有兴趣的可以试试。
原文地址https://www.cnblogs.com/kumbayaco/p/11334885.html

目录
打赏
0
0
0
0
48
分享
相关文章
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
327 0
揭秘Unity物理引擎核心技术:从刚体动力学到关节连接,全方位教你如何在虚拟世界中重现真实物理现象——含实战代码示例与详细解析
【8月更文挑战第31天】Unity物理引擎对于游戏开发至关重要,它能够模拟真实的物理效果,如刚体运动、碰撞检测及关节连接等。通过Rigidbody和Collider组件,开发者可以轻松实现物体间的互动与碰撞。本文通过具体代码示例介绍了如何使用Unity物理引擎实现物体运动、施加力、使用关节连接以及模拟弹簧效果等功能,帮助开发者提升游戏的真实感与沉浸感。
507 1
从零起步,深度揭秘:运用Unity引擎及网络编程技术,一步步搭建属于你的实时多人在线对战游戏平台——详尽指南与实战代码解析,带你轻松掌握网络化游戏开发的核心要领与最佳实践路径
【8月更文挑战第31天】构建实时多人对战平台是技术与创意的结合。本文使用成熟的Unity游戏开发引擎,从零开始指导读者搭建简单的实时对战平台。内容涵盖网络架构设计、Unity网络API应用及客户端与服务器通信。首先,创建新项目并选择适合多人游戏的模板,使用推荐的网络传输层。接着,定义基本玩法,如2D多人射击游戏,创建角色预制件并添加Rigidbody2D组件。然后,引入网络身份组件以同步对象状态。通过示例代码展示玩家控制逻辑,包括移动和发射子弹功能。最后,设置服务器端逻辑,处理客户端连接和断开。本文帮助读者掌握构建Unity多人对战平台的核心知识,为进一步开发打下基础。
447 0
揭秘游戏沉浸感的秘密武器:深度解析Unity中的音频设计技巧,从背景音乐到动态音效,全面提升你的游戏氛围艺术——附实战代码示例与应用场景指导
【8月更文挑战第31天】音频设计在游戏开发中至关重要,不仅能增强沉浸感,还能传递信息,构建氛围。Unity作为跨平台游戏引擎,提供了丰富的音频处理功能,助力开发者轻松实现复杂音效。本文将探讨如何利用Unity的音频设计提升游戏氛围,并通过具体示例代码展示实现过程。例如,在恐怖游戏中,阴森的背景音乐和突然的脚步声能增加紧张感;在休闲游戏中,轻快的旋律则让玩家感到愉悦。
447 0
【Unity光照艺术手册】掌握这些技巧,让你的游戏场景瞬间提升档次:从基础光源到全局光照,打造24小时不间断的视觉盛宴——如何运用代码与烘焙创造逼真光影效果全解析
【8月更文挑战第31天】在Unity中,合理的光照与阴影设置对于打造逼真环境至关重要。本文介绍Unity支持的多种光源类型,如定向光、点光源、聚光灯等,并通过具体示例展示如何使用着色器和脚本控制光照强度,模拟不同时间段的光照变化。此外,还介绍了动态和静态阴影、全局光照及光照探针等高级功能,帮助开发者创造丰富多样的光影效果,提升游戏沉浸感。
393 0
深度解析Unity游戏开发中的性能瓶颈与优化方案:从资源管理到代码执行,全方位提升你的游戏流畅度,让玩家体验飞跃性的顺滑——不止是技巧,更是艺术的追求
【8月更文挑战第31天】《Unity性能优化实战:让你的游戏流畅如飞》详细介绍了Unity游戏性能优化的关键技巧,涵盖资源管理、代码优化、场景管理和内存管理等方面。通过具体示例,如纹理打包、异步加载、协程使用及LOD技术,帮助开发者打造高效流畅的游戏体验。文中提供了实用代码片段,助力减少内存消耗、提升渲染效率,确保游戏运行丝滑顺畅。性能优化是一个持续过程,需不断测试调整以达最佳效果。
418 0
【unity小技巧】unity通过代码进行更改后处理效果
【unity小技巧】unity通过代码进行更改后处理效果
219 0
【unity小技巧】手戳代码程序化绘制地形Terrain树和预制体物品、动物
【unity小技巧】手戳代码程序化绘制地形Terrain树和预制体物品、动物
230 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问