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: Plugins\Scripts下的代码 (一般还有个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编译代码的宏,来自于几个地方:
a. Build setting defines
b. asmdef内的定义
c. 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安装目录都不一样,所以需要通用化。有两个方法:
a. 将dll拷贝到工程同级目录,将ref hintpath改成相对路径(不过,在unity升级后,此目录也需要升级,不适合unity需要频繁升级的项目)
b. 添加环境变量UNITY_PATH,修改csproj,示例如下
csproj的Condition可以很好的解决不同环境下的一致性问题
- Include scripts问题
由于涉及到多人协作,我们的csproj没有采取正则include,而是显式的include了每个代码文件,这样产生了两个问题
a. 所有人都需要提交csproj,而csproj默认是将新加的代码添加至末尾,所以在多人同时新加文件时,很容易产生冲突,而且不能自动resolve,需要手动合并。
b. 若引入了第三方的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的编译环节有所了解。切换过来后,感觉是一种新的体验,有兴趣的可以试试。
Unity工程无代码化的更多相关文章
- unity工程接入Android sdk后真机测试解锁屏后退出的解决
unity工程接入如91.移动支付等Android sdk后,真机运行尤其是在4.0+以上坏境,往往会出现解锁屏后退出的情况,解决办法如下: 可以在AndroidManifest.xml中所有的con ...
- 【Unity_UWP】Unity 工程发布win10 UWP 时的本地文件读取 (下篇)
Universal Windows Platform(UWP)是微软Windows10专用的通用应用平台,其目的在于在统一操作系统下控制所有智能电子设备. 自从Unity 5.2之后,配合VS 201 ...
- 【Unity_UWP】Unity 工程发布win10 UWP 时的本地文件读取 (上篇)
Universal Windows Platform(UWP)是微软Windows10专用的通用应用平台,其目的在于在统一操作系统下控制所有智能电子设备. 自从Unity 5.2之后,配合VS 201 ...
- 升级MAC OS到10.13, 10.14系统后UNITY工程无法加载资源的解决办法
升级MAC OS到10.13, 10.14系统后,出现UNITY工程无法加载资源的情况: Unity项目中Asset目录显示为空! 解决办法一: 打开Launchpad中的磁盘工具 (也就是实用工具下 ...
- Unity工程资源破解
Unity工程资源提取其实还是很方便的,网上也有很多相关介绍,比如雨凇就专门写了一遍关于破解Unity资源的文章(http://www.xuanyusong.com/archives/3618 ...
- Unity中无GC Alloc的CalculateFrustumPlanes
如果你需要在逻辑层做一些预先的剔除操作,可能需要从MainCamera构建视锥体,然后进行简易相交测试,这时候在unity里面用到的函数接口是CalculateFrustumPlanes: names ...
- Maven工程无异常 启动没有出现Starting ProtocolHandler的原因
这个情况可能的原因 一般来说有3种1.数据库没连接上2.注册中心没连接上3.逆向工程生成的mapper 有问题解决:哪个Maven工程出问题,就那个工程的src/main/resource目录下面添加 ...
- Unity工程3D和2D开发模式切换
在新建工程时,经常会选择默认的3D工程,但是如果想做2D游戏又不小心选了3D工程呢,总不能把工程删了重新建吧,有个办法就是打开 Edit > Project Settings > Edit ...
- VS2010打开旧版本MFC工程无对话框
解决方案: 左侧有个"资源视图",打开,里面就能找得到对话框,如果没有资源视图,就在菜单的视图选项里打开资源视图!
随机推荐
- POJ 1966:Cable TV Network(最小点割集)***
http://poj.org/problem?id=1966 题意:给出一个由n个点,m条边组成的无向图.求最少去掉多少点才能使得图中存在两点,它们之间不连通. 思路:将点i拆成a和b,连一条a-&g ...
- 关于ArrayList的扩容机制
关于ArrayList的扩容机制 ArrayList作为List接口常用的一个实现类,其底层数据接口由数组实现,可以保证O(1) 复杂度的随机查找, 在增删效率上不如LinkedList,但是在查询效 ...
- netty实现的RPC框架
自己手撸了一个nettyRPC框架,希望在这里给有兴趣的同学们做个参考. 要想实现nettyrpc需要了解的技术要点如下: spring的自定义注解.spring的bean的有关初始化. 反射和动态代 ...
- 一个简单的使用mock技术进行测试的例子
Account: public class Account { private String acountId; private long balance; public Account(String ...
- go 格式化 int,位数不够0补齐
n := 32 sInt := fmt.Sprintf("%07d", n)
- Jmeter--录制脚本-用户参数化-添加断言
使用jmeter实现的场景 1.使用badboy录制脚本 2.使用jmeter自带元件进行用户参数化 3.给请求添加断言(给请求添加检查点) 使用badboy录制脚本导入jmeter 1.输入http ...
- Spring Cloud中Hystrix、Ribbon及Feign的熔断关系是什么?
导读 今天和大家聊一聊在Spring Cloud微服务框架实践中,比较核心但是又很容易把人搞得稀里糊涂的一个问题,那就是在Spring Cloud中Hystrix.Ribbon以及Feign它们三者之 ...
- MVC+EFCore 完整教程18 -- 升级分布视图至 View Component
之前我们详细介绍过分布视图(partial view),在有一些更加复杂的场景下,.net core为我们提供了更加强大的组件 view component, 可以认为view component是 ...
- Apache Tomcat 绿色版安装Service(服务)
1.配置CATALINA_HOME的环境变量: 变量名:CATALINA_HOME 值:tomcat安装或解压的根目录如:c:\Apache tomcat6.0 2.开始->运行->c ...
- Number() 与 parseInt()解析
在 Python 中,将字符串转为整型变量的函数是 int() ,直接使用 int("123")就可以得到 123的输出结果,这样可以比较快速的得到我们想要的结果,在 js 中将 ...