使用 Mono.Cecil 辅助 Unity3D 手游进行性能测试(续)

本文严禁转载。

之前的方法及其局限

问题背景和最初的尝试见这里。最开始的想法比较简单,只想着利用 PostprocessBuild 这个事件,来对已经准备好的本地工程文件(iOS 或 Android)中的 .NET 程序集进行注入。但是,这样做限制很多。

首先,无法对 IL2CPP 作为 Scripting Backend 的情况进行注入。因为触发这个事件时,本地工程文件中没有 .NET 程序集,只有 C++ 代码,无法用 Cecil 进行注入。

第二,Android 平台,用 Mono2x 作为 Scripting Backend 的情况下,也需要打包为 Android Studio Project 才能使用。对于直接打包成 apk 的情况,无法简单的进行注入(除非使用解包、注入、重新签名打包的方法,比较麻烦)。

第三,iOS 平台,即使用 Mono2x 作为 Scripting Backend,也无法成功。这是因为在 iOS 平台打包需要先进行一个叫 AOT Cross Compiling 的步骤,对所有的程序集生成对应的 .dll.s 文件。这些文件包含的信息会在运行时被校验,如果我篡改了程序集,而没有理会 .dll.s 文件,在运行时会报错。错误信息类似

A script behaviour (probably XXX?) has a different seralization layout when loading. (Read ** bytes but expected ** bytes)

Did you #ifdef UNITY_EDITOR a section of your serialized properties in any of your scripts?

其中 XXX 是 .NET 脚本名称,两组星号表示两个不同值。这错误最终导致脚本加载失败,无法运行游戏。与错误信息描述不同,我并没有在出问题的脚本上写任何条件编译的代码。要想解决这个问题,估计需要篡改 .dll.s 文件才可以,仍然是很不经济的。

 

篡改编译器的方法

接下来一个办法,就是对 Unity 的 C# 编译器 mcs.exe 进行篡改。我没有深入实验,因为几个简单的实验就耗费了一天多的时间。我主要尝试了两种方法,当然,都没成功。

方法一,将原 mcs.exe 重命名(如 mcs1.exe),而后自己写一个 .NET 控制台应用程序,占据原来 mcs.exe 的位置,在其中用 System.Diagnostic.Process 类来启动 mcs1.exe。这个过程中,我对 Process 对象的一些配置,如环境变量(EnvironmentVariables 属性)、输入输出重定向(RedirectStandardXXX 属性)进行了多种排列组合,仍无法正确调用 mcs1.exe,就更不要说调用之后的事情了。

方法二,直接在 mcs.exe 中注入代码。因为 mcs.exe 也是一个 .NET 应用程序,并且看上去未经混淆,所以直接注入是可行的。即,「把向游戏程序集中注入代码的代码,注入到编译器中。」这样做主要的问题,是 mcs.exe 的输出目录是临时文件夹,无法保证其中有我们依赖的(如注入后写入程序集时,需要用 Mono.Cecil 的 DefaultAssemblyResolver 进行解析的)程序集。

通过PostprocessScene回调事件来进行注入

Unity 虽然没有在执行 mcs.exe 和后续步骤(IL2CPP、Android 打包 apk、iOS 上的 AOT 交叉编译等)之间提供回调,但是回调事件 OnPostprocessScene 目前是确保在它们之间至少触发一次的。多亏 https://github.com/rayosu/UnityDllInjector 提醒了我。在这个事件回调中处理 DLL,理论上在任何平台、任何 Scripting Backend 上都可以有效注入。实现过程中有几个要点需要注意:

  • 事件 OnPostprocessScene 对应 Build Settings 中指定打包的场景个数,所以它可能执行多次,故而需要防止重复。除了上述 UnityDllInjector 中提供的方法,还可以直接把注入标记写入你的目标程序集。但值得注意的是,新增一个用于标记的空类在 iOS + Mono2x 下又是不好用的,猜测还和 AOT 交叉编译有关。保险的做法之一,是在游戏代码中保留几个 bool 常量,值为 false,注入前检查相应的值,如果为 true 则跳过,否则注入。注入完成后,将相应的 bool 常量篡改为 true 即可。
  • 游戏脚本对应的程序集,在注入时一定处于和 Assets 同级的 Library 下的 ScriptAssemblies 文件夹下,但要注意你依赖的 Unity 程序集。我使用 UnityDllInjector 提供的方法,依然不能保证获取到需要的程序集。最终我采用的方法是,使用 EditorApplication.applicationContentsPath 获取 Unity 安装目录,在其中 Data/Managed 目录里寻找必要的程序集。

目前我测试了 Android + Mono/IL2CPP 和 iOS + IL2CPP,都没有问题。iOS + Mono2x 可能由于我们项目本身的一些问题,在 Xcode 链接阶段有一些问题。

时间: 2024-10-28 22:49:58

使用 Mono.Cecil 辅助 Unity3D 手游进行性能测试(续)的相关文章

使用 Mono.Cecil 辅助 Unity3D 手游进行性能测试

Unity3D 引擎在  UnityEngine 名字空间下,提供了  Profiler 类(Unity 5.6 开始似乎改变了这个名字空间),用于辅助对项目性能进行测试.以 Android 平台为例,在构建之前,需要在 Unity 的 File/Build Settings 菜单项弹出的窗口中,勾选 Development Build 一项.后用  adb forward  的方式,将 Android 设备的 TCP 输出转发到电脑,实现和 Unity Profiler 的连接(网上很容易找到

Unity3D手游开发实践

<腾讯桌球:客户端总结> 本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目本身.虽然基于Unity3D,很多东西同样适用于Cocos.本文从以下10大点进行阐述: 架构设计 原生插件/平台交互 版本与补丁 用脚本,还是不用?这是一个问题 资源管理 性能优化 异常与Crash 适配与兼容 调试及开发工具 项目运营 ? 1.架构设计 好的架构利用大规模项目的多人团队开发和代码管理,也利用查找错误和后期维护. 框架的选择:需要根据团队.项目来进行选择,没有最好的框架,只有最合适的框架. 框架的使

[unity3d]手游资源热更新策略探讨

原地址:http://blog.csdn.net/dingxiaowei2013/article/details/20079683 我们学习了如何将资源进行打包.这次就可以用上场了,我们来探讨一下手游资源的增量更新策略.注意哦,只是资源哦.关于代码的更新,我们稍后再来研究.理论上这个方案可以使用各种静态资源的更新,不仅仅是assetbundle打包的. (转载请注明原文地址http://blog.csdn.net/janeky/article/details/17666409) 原理 现在的手游

Unity3D手游开发日记(6) - 适合移动平台的水深处理

市面上大部分的手机游戏,水面都比较粗糙,也基本没发现谁做过水深的处理. 水深的处理在PC平台比较容易,因为很容易获得每个像素的深度,比如G-Buffer,有了像素的深度,就能计算出每个像素到水面的距离,实现水深alpha渐变. 但是在移动平台,又是万恶的浮点纹理...导致此方案不行. 但是方案都是人想出来的,我想了两种适合移动平台的方案 方案1:用水面顶点颜色保存alpha值来做水深渐变. 这种方案,要求水面的模型面片是格子的,就像地形网格一样,格子越密,alpha的精度才越高. 方案2:用贴图

unity3D手游地图设计的四大类型 哪种适合你?

据报道/最近,小编在外媒看到一篇有关手游地图设计方面的博客,英文作者Junxue Li(李俊学)是游戏美术外包公司Novtilus Art的CEO,他在博客中讨论了四种不同类别的手游地图以及各自适合的手游类型,并且谈到了这些地图类型的优势与不足,这里分享给业内的童鞋们,希望可以有所帮助,以下是狗刨学习网编译的博客内容: 我们的团队为一些休闲游戏做过地图,包括三消.泡泡龙.老虎机游戏等等内容,其实,这些不同类型的手游的地图其实是比较类似的,都有线性升级进度,而且可以通过地图形式展现出升级的过程.

Unity3D手游开发日记(9) - 互动草的效果

所谓互动草,就是角色跑动或者释放技能,能影响草的摆动方向和幅度. 前面的文章早已经实现了风吹草动的效果,迟迟没有在Unity上面做互动草,是因为以前我在端游项目做过一套太过于牛逼的方案.在CE3的互动草的基础上扩展,效果好,但技术太复杂,效率开销也特别高. 如果在手机上,就得做一套简单高效的. 实现效果:从任意方向碰一下草,草就应该来回晃动,晃动幅度逐渐减小.多次触碰,效果应该叠加.这样的话就比较真实. 实现原理:用正玄波实现草来回摆动的简谐运动,用指数衰减来模拟阻力 实现步骤: 1.每个草挂一

Unity3D手游-横版ACT游戏完整源码下载

说明: 这不是武林,这不是江湖,没有道不完的恩怨,没有斩不断的情仇,更没有理不清的烦恼,这是剑的世界,一代剑魁闯入未知世界,将会为这个世界展开什么样的蓝图,让你来创造它的未来,剑魁道天下,一剑斗烛龙!!! 游戏开发了三个月,非常值得收藏,至于做什么用途,就看你自己啦!来来来,放大招了!请看附件:) 测试环境: Unity3D 4.3.4 运行效果: 完整源码下载http://www.yxkfw.com/thread-5035-1-1.html

Unity3D 手游开发中所有特殊的文件夹

这里列举出手游开发中用到了所有特殊文件夹. 1.Editor Editor文件夹可以在根目录下,也可以在子目录里,只要名子叫Editor就可以.比如目录:/xxx/xxx/Editor  和 /Editor 是一样的,无论多少个叫Editor的文件夹都可以.Editor下面放的所有资源文件或者脚本文件都不会被打进发布包中,并且脚本也只能在编辑时使用.一般呢会把一些工具类的脚本放在这里,或者是一些编辑时用的DLL. 比如我们现在要做类似技能编辑器,那么编辑器的代码放在这里是再好不过了,因为实际运行

Unity3D手游开发日记(4) - 适合移动平台的热浪扭曲

热浪扭曲效果的实现,分两部分,一是抓图,二是扭曲扰动.其中难点在于抓图的处理,网上的解决方案有两种,在移动平台都有很多问题,只好自己实现了一种新的方案,效果还不错. 网上方案1. 用GrabPass抓图 GrabPass在有的手机上是不支持的...效率也是问题,所以... 代码可以看看: [csharp] view plain copy Shader "Luoyinan/Distortion/HeatDistortion" { Properties { _NoiseTex ("