不要忽视Managed code stripping的副作用
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种方法可以避免类似脚本丢失的问题。
- 在构建的场景中引用所需的脚本,以防止在构建项目时剔除需要的代码。
如图,将PlayableDirector组件和一个空的Timeline对象添加到场景中。
2. 在脚本中引用所需的类,以防止在构建项目时剔除需要的代码。
3. 添加一个link.xml文件,以防止UnityLinker剔除所需的代码。
可以在下面的代码仓库中查看这三种方式的示例,4个分支分别代表了会被剔除代码(Master)以及3种防止代码被错误剔除的方式。
https://github.com/chenjd/CodeStripExamplegithub.com
0x03 结论
如果你开启了代码剔除功能以减小构建的包体大小,那么请留意Unity是否会剔除你在运行时所需的代码,例如反射相关的代码等等。 特别是对于那些使用IL2CPP脚本运行时的平台(例如iOS),默认情况下会启用代码剔除。 如果使用Assetbundle管理资源,则需要注意不要删除所需的代码。
不要忽视Managed code stripping的副作用的更多相关文章
- Optimize Managed Code For Multi-Core Machines
Parallel Performance Optimize Managed Code For Multi-Core Machines Daan Leijen and Judd Hall This ar ...
- Passing JavaScript Objects to Managed Code
Silverlight If the target managed property or input parameter is strongly typed (that is, not typed ...
- How to: Synchronize Files by Using Managed Code
The examples in this topic focus on the following Sync Framework types: FileSyncProvider FileSyncOpt ...
- [转]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 ...
- [转]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 ...
- [转]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 ...
- Native code on Windows Phone 8(转)
Windows Phone 8 introduces the ability to use native code to implement Windows Phone. In this sectio ...
- 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 ...
- code 代码分析 及其解决方案
官网地址:http://msdn.microsoft.com/zh-cn/library/ms182135.aspx [FxCop.设计规则]11. 不应该使用默认参数 参考地址:http://blo ...
随机推荐
- Linux平台下_tomcat的安装与优化
一.Tomcat介绍 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选.对于一 ...
- 搭建WordPress个人博客
1. 准备LNMP环境 LNMP 是 Linux.Nginx.MySQL 和 PHP 的缩写,是 WordPress 博客系统依赖的基础运行环境.我们先来准备 LNMP 环境 安装Nginx 使用 y ...
- Linux的iptables菜鸟初学
什么是iptables? iptables是linux下的命令行工具,操控的是linux的防火墙,这个防火墙叫netfilter.通俗的说应该是用户通过iptables把安全设定设置给netfilte ...
- 88)PHP,PDOStatement对象
PDOStatement类,称之为PDO语句对象,SQL执行完(处理完)产生的结果对象. fetchColumn(index=) 允许传递参数,表示获得第一条记录的第几个字段的值. 相当于 getOn ...
- mysql 多字段更新
更新一个字段当好写 ; Query OK, rows affected (17.36 sec) Rows matched: Changed: Warnings: 问题是想更新多个字段sql serve ...
- [LC] 277. Find the Celebrity
Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...
- 详解JavaScript Document对象
转自:http://segmentfault.com/a/1190000000660947 在浏览器中,与用户进行数据交换都是通过客户端的javascript代码来实现的,而完成这些交互工作大多数是d ...
- ArrayList查找和添加元素问题
问题描述: 如上图所示,如果依靠迭代器在List中查找元素并添加元素,会报错:java.util.ConcurrentModificationException原因是在添加元素后,List本身发生了变 ...
- iOS(Swift)学习笔记之SwiftyJSON的使用
本文为原创文章,转载请标明出处 1. 通过CocoaPods安装SwiftyJSON platform :ios, '10.0' target '<Your Target Name>' d ...
- 吴裕雄--天生自然python学习笔记:Python3 模块
Python3 模块 在前面的几个章节中我们脚本上是用 python 解释器来编程,如果你从 Python 解释器退出再进入,那么你定义的所有的方法和变量就都消失了. 为此 Python 提供了一个办 ...