【李剑英]】我为什么想干掉Unity3d?
这个问题容我先不回答,每个做技术的人多少都有点完美主义情结。在使用Unity3D(以下简称U3D)的过程中,大家是否都经历着痛并快乐着的体验呢?下面我就从国内较为普遍的两个痛点说起。
痛点分析
痛点一:il2cpp带来的困扰
自Unity采用il2cpp决策以来,程序员们苦不堪言。每当接入iOS平台时,就如同经历一场磨难;每次看到打包后的文件容量,压力便扑面而来。
痛点二:底层API未公开
Unity的底层C++ API并未公开,若要接入脚本层,只能通过Dotnet进行互操作。这使得在U3D平台上难以实现较为完美的脚本方案,性能问题尤为突出。
痛点三:手机平台无法断点调试
断点调试本是程序员调试代码的最后手段,但在Unity的手机平台上却无法使用,这着实令人担忧。
既然有这么多痛点,为何大家还一直使用Unity3D呢?这是因为Unity3D也有一些十分吸引人的优点:
- 成熟、稳定的IDE:不过其稳定性要打些折扣。
- 多平台一键发布:虽然在iOS平台上是发布为Xcode项目,一键发布的体验稍差。
- C#语言加持:C#语言为开发带来了一定的便利。
解决痛点的可能性
有没有办法既能解决上述痛点,又能保持Unity3D的优势呢?答案是肯定的。
Unity3D架构分析
Unity3D以C++编写的引擎框架为基础,这是比较传统的做法。但它的反传统之处在于,将所有接口都置于MonoRuntime之后,Unity自身的部分功能(如UnityEngine.UI)也是由Dotnet开发,用户代码更是完全限制为使用Dotnet开发。虽然Unity提供了Plugin机制,允许使用其他语言混编,但这些插件均无法访问Unity底层C++代码(至少目前我未见到相关资料)。这就导致Unity难以高效接入C++实现的脚本语言,Lua在Unity中的实际表现就是例证。这便是痛点二的原因,而痛点一可以说是Unity自身决策的问题,痛点三则是其工作的不足。
解决方案
基于Xamarin方案,我们可以解决上述痛点:
- 断点调试:在Android和iOS平台均可实现断点调试。
- 脚本接入:底层代码同时对MonoRuntime和脚本层公开接口,能够插入C++实现的各种脚本(如Lua),并获得原生性能。
- 代码分离:用户代码分为Dotnet和脚本两种,两者不直接互访,而是通过底层接口互发消息。这样一来,也就无需担心il2cpp的问题了。此外,还能使用C# 5.0的特性。
不过,Xamarin平台上现有的MonoGame,同样是在MonoRuntime之后实现的,调用OTK,无法提供原生性能,也不能插入原生脚本。
该方案的具体实现步骤如下:
- 编写原生插件:为Xamarin编写不同平台(主要是iOS、Android和PC)的原生插件,涵盖绘图、音效、触摸、键盘等底层公开接口。在PC上可以不使用Xamarin,而是采用Windows + VS的组合,这样在Windows上调试会更加方便。
- 接口导出:通过P/invoke将接口导出到Dotnet,并针对不同的脚本层进行相应的导出。
采用这种方式,重度用户代码可以使用Dotnet编写,轻度易变代码则使用脚本编写,轻度代码作为资源,可在任何平台下载执行。
保持优势的实现
C#加持
相比Unity整合的C# 3.5,Xamarin整合了C# 5.0,进一步提升了开发体验。
多平台一键发布
- Android平台:实现较为容易,我们已经完成了原理测试程序。具体做法是,准备一个模板APK文件,解包后将资源放入,再重新打包签名。同时,将Android上的Dotnet用户代码一键编译成DLL作为资源放入,由于Android上的MonoRuntime使用的是JIT,这一过程很容易实现。
- iOS平台:一键发布相对麻烦,需要使用MonoAOT将Dotnet用户代码编译为.a文件,再用模板包重签名。目前我对将AOT编译成.a文件以及IPA重签名的具体操作不太清楚,但我们可以参考Unity源码和畅游的引擎源码学习AOT编译,对于IPA重签名,可以借鉴国内越狱平台的功能以及著名软件iResign的源码。实现一键发布后,发布阶段将不再依赖Xamarin,Xamarin仅需提供模板包,这样还能为用户节省Xamarin授权的费用。
成熟稳定的场景编辑器
可以借鉴UnityEditor的脚本扩展方式,自行开发成熟稳定的场景编辑器。
这就是新FB引擎的发展方向。
支持与讨论
如果你想支持赞助我们的工作,可以使用支付宝转账至:lightsever@hotmail.com
如果你想加入讨论,可以加入QQ群:223823428
李剑英