0x00 前言

Unity 2018.3之后,新的“Managed Stripping Level”选项将替换 player settings 中原有的“Stripping Level”选项。 这个新的选项可用于所有平台以及Mono和IL2CPP脚本运行时。而这个功能的主要目的则是通过删除一些未使用的代码来减小应用程序的大小。 嗯,听起来不错,但这里存在一个潜在的副作用,即Unity如何知道哪些代码才是未使用的代码呢?

0x01 Load From Assetbundle 以及 “the script is missing”

但是,在继续讨论代码剔除流水线之前,让我们看一下由于代码剔除导致问题的一个情景。

现在,让我们在编辑器中创建一个Cube和一个Timeline资源。 使用Timeline,我们可以将Cube从A点移动到B点。

为了更好地管理和更新资源,我们将场景中的Cube制作为Prefab并将Cube本身从场景中删除。 然后,我们将这个prefab和Timeline资源制成AssetBundle,以便在运行时动态加载资源。

我们可以在编辑器中加载Assetbundle并实例化Prefab,然后我们可以看到Cube开始了从点A到点B的移动——Timeline的脚本生效了。

 

此时,这个工作流似乎工作正常: 从场景中删除资源,将它们放入Assetbundle中,并在运行时动态加载它们。

之后,我们将项目构建到iOS平台,运行相同的场景并加载相同的Assetbundle以在运行时创建Cube对象。 但是这次,Cube并没有开始按预期移动,并且我们从Unity收到了一条错误消息。

“The referenced script (UnityEngine.Timeline.AnimationTrack) on this Behaviour is missing!”

Timeline的脚本丢失了,并且导致了Cube无法在iOS平台上移动。

0x02 代码剔除流水线

丢失与Timeline相关的脚本的原因是,在构建iOS版本时Unity删除了相关代码。

首先要注意的是,iOS使用IL2CPP脚本运行时。 因为Apple的App Store不再接受Mono版本,并且iOS 11及更高版本也不支持Mono。 而选择IL2CPP脚本运行时的时候,“Managed code stripping”的“Disabled”选项将不可用。 这意味着当我们选择IL2CPP脚本运行时的结果就是无法关闭代码剔除。

要注意的第二件事是代码剔除流水线本身。 Unity的Build Pipeline会使用一个称为UnityLinker的工具来剔除托管代码。该过程的工作方式是定义root assemblies,然后使用静态代码分析来确定这些root assemblies还要使用哪些其他的托管代码。 之后删除所有无法访问的代码,即所谓的未使用代码。 其中Unity Engine的程序集也是有可能被剥离的。 root assemblies是Unity Editor根据用户脚本代码编译的程序集,例如Assembly-CSharp.dll。同时构建中包含的场景也会被视为root。

因此,在运行时从Assetbundle加载资产时,至少有3种方法可以避免类似脚本丢失的问题。

  1. 在构建的场景中引用所需的脚本,以防止在构建项目时剔除需要的代码。

如图,将PlayableDirector组件和一个空的Timeline对象添加到场景中。

2. 在脚本中引用所需的类,以防止在构建项目时剔除需要的代码。

3. 添加一个link.xml文件,以防止UnityLinker剔除所需的代码。

可以在下面的代码仓库中查看这三种方式的示例,4个分支分别代表了会被剔除代码(Master)以及3种防止代码被错误剔除的方式。

https://github.com/chenjd/CodeStripExample​github.com

0x03 结论

如果你开启了代码剔除功能以减小构建的包体大小,那么请留意Unity是否会剔除你在运行时所需的代码,例如反射相关的代码等等。 特别是对于那些使用IL2CPP脚本运行时的平台(例如iOS),默认情况下会启用代码剔除。 如果使用Assetbundle管理资源,则需要注意不要删除所需的代码。

不要忽视Managed code stripping的副作用的更多相关文章

  1. Optimize Managed Code For Multi-Core Machines

    Parallel Performance Optimize Managed Code For Multi-Core Machines Daan Leijen and Judd Hall This ar ...

  2. Passing JavaScript Objects to Managed Code

    Silverlight If the target managed property or input parameter is strongly typed (that is, not typed ...

  3. How to: Synchronize Files by Using Managed Code

    The examples in this topic focus on the following Sync Framework types: FileSyncProvider FileSyncOpt ...

  4. [转]Passing Managed Structures With Strings To Unmanaged Code Part 3

    1. Introduction. 1.1 In part 1 of this series of blogs we studied how to pass a managed structure (w ...

  5. [转]Passing Managed Structures With Strings To Unmanaged Code Part 2

    1. Introduction. 1.1 In part 1 of this series of blogs we studied how to pass a managed structure (w ...

  6. [转]Passing Managed Structures With Strings To Unmanaged Code Part 1

    1. Introduction. 1.1 Managed structures that contain strings are a common sight. The trouble is that ...

  7. Native code on Windows Phone 8(转)

    Windows Phone 8 introduces the ability to use native code to implement Windows Phone. In this sectio ...

  8. Calling C++ code from C# z

    http://blogs.msdn.com/b/borisj/archive/2006/09/28/769708.aspx I apologize for the long delay for thi ...

  9. code 代码分析 及其解决方案

    官网地址:http://msdn.microsoft.com/zh-cn/library/ms182135.aspx [FxCop.设计规则]11. 不应该使用默认参数 参考地址:http://blo ...

随机推荐

  1. Nginx_安全2

    Nginx与安全有关的配置 隐藏版本号 http {    server_tokens off;} 经常会有针对某个版本的nginx安全漏洞出现,隐藏nginx版本号就成了主要的安全优化手段之一,当然 ...

  2. iTOP-4418开发板_重实力_优势突出_有原理图源码开源

    核心板参数 尺寸:50mm*60mm 高度:核心板连接器组合高度1.5mm PCB层数:6层PCB沉金设计 4418 CPU:ARM Cortex-A9 四核 S5P4418处理器 1.4GHz 68 ...

  3. 2019-2020-1 20199324《Linux内核原理与分析》第六周作业

    第五章 系统调用的三层机制(下) 1.给MenuOS增加命令 进入Linuxkernel目录下,强制删除当前menu目录,再重新克隆一个新版本的menu 进入menu,运行make roofts脚本就 ...

  4. 40)PHP,mysql_fetch_row,mysql_fetch_array,mysql_fetch_assoc的区别

    分析: mysql_fetch_row,这个函数是从结果集中取一行作为枚举数据,从和指定的结果标识关联的结果集中取得一行数据并作为数组返回.每个结果的列储存在一个数组的单元中,偏移量从 开始. 注意, ...

  5. 吴裕雄--天生自然python学习笔记:python 用pygame模块角色类(Sprite)移动与碰撞

    角色类(Sprite) Py game 游戏中有许多组件会重复用到,比如射击宇宙飞船的游戏中,外星宇宙 飞船可能多达数十艘 , 通过创建“角色类”,可以生成多个相同的对象. Py game 角色类是游 ...

  6. js使用心得——避免全局变量冲突的小技巧

    在写js代码的时候,经常会因为这样或者那样的原因用到全局变量,如果全局变量只在一个js里使用,那就没问题,但如果变量在不同的js文件里出现,这时隐藏的问题就会开始暴露,也许你能很快修复出现的BUG,又 ...

  7. 二评北科团委:“斩首计划”进行时,其用心也毒

    近日,在同学们和热心群众的共同努力下,各高校相继悬崖勒马,北大马会.北语新新青年.人大新光等进步社团均顺利注册.而北科团委倒行逆施,可谓一枝独秀,对于齐民学社的同学们的诉求,不仅不予以回应,反而采取表 ...

  8. C++逆序输出字符串

    使用库函数 //使用库函数 #include <iostream> #include <string> #include <algorithm> using nam ...

  9. OpenSSL之X509系列

    OpenSSL之X509系列之1---引言和X509概述 [引言]    X509是系列的函数在我们开发与PKI相关的应用的时候我们都会用到,但是OpenSSL中对X509的描述并不是很多,鉴于些,我 ...

  10. 吴裕雄--天生自然HTML学习笔记:HTML 属性

    属性是 HTML 元素提供的附加信息. HTML 属性 HTML 元素可以设置属性 属性可以在元素中添加附加信息 属性一般描述于开始标签 属性总是以名称/值对的形式出现,比如:name="v ...