Unity 代码裁剪(Strip Engine Code)
文章目录
- 0.IL2CPP 打包运行闪退问题
- 1.什么是代码裁剪
- 2.为什么要使用代码裁剪
- 3.代码裁剪设置与级别
- 4.强制保留代码
- 4.1 使用[Preserve]标签
- 4.2 使用Link.xml文件
- 5.Strip中遇到的问题及解决方法
- 6.注意事项
0.IL2CPP 打包运行闪退问题
Google Play要求从2019年8月1日起apk必须支持64位CPU, 否则就下架或不让上. 使apk支持ARM64就需要把Scripting Backend由Mono切换为IL2CPP
那么问题来了, 通过IL2CPP打出的包往往不能正常运行(闪退,报错).
其原因就是, BuildSetting里默认勾选了代码裁剪, 取消勾选打出的apk就能正常运行,但是包体也会变大
1.什么是代码裁剪
官方文档
简而言之:开启代码裁剪,能够在build时将项目中没有用到的代码裁减掉,以减少build出的代码量。
Strip的主要作用在于裁剪系统库、Unity引擎代码、插件代码,往往它们包含了大量对工程无用的代码。
勾选代码裁剪,构建时Unity代码裁剪工具会分析项目中的程序集,查找和删除未使用的代码. 裁剪掉没有使用到的代码.比如,一款2D游戏只用到了Sprite, 2D物理组件, 就可以把没有用到的3D物理代码部分裁剪掉. 使用裁剪功能可以显著减小包体大小, 也是目前Unity游戏包体优化的一个重要环节.
2.为什么要使用代码裁剪
显著减小包体大小
:开启代码裁剪,在build时将项目中没有用到的代码裁减掉,以减少build出的代码量加快cpp生成的过程
:如果使用了il2cpp,由于build过程中先生成CIL然后再生成cpp代码。所以开启代码裁减之后,能减少CIL的生成,从而加快cpp生成的过程。
3.代码裁剪设置与级别
File->Build Settings->Player Settings->Optimization->Managed Stripping Level
属性 | 功能 |
---|---|
Disabled | Unity 不会删除任何代码。此设置仅可见,并且是使用 Mono 脚本后端时的默认设置。 |
Minimal | Unity 仅在 UnityEngine 和 .NET 类库中搜索未使用的代码。Unity 不会删除任何用户编写的代码。此设置最不可能导致任何意外的运行时行为。此设置对于可用性比构建大小更重要的项目很有用。如果您使用 IL2CPP 脚本后端,这是默认设置。 |
Low | Unity 会搜索部分用户编写的程序集以及所有 UnityEngine 和 .NET 类库以查找未使用的代码。此设置会应用一组规则,删除部分未使用的代码,但会将出现意外后果的可能性降至最低,例如使用反射的运行时代码的行为发生变化。 |
Medium | Unity 会部分搜索所有程序集以查找无法访问的代码。此设置应用一组规则,可删除更多类型的代码模式以减小构建大小。虽然 Unity 不会删除所有可能无法访问的代码,但此设置确实会增加不良或意外行为更改的风险。 |
High | Unity 会对所有程序集进行广泛搜索,以查找无法访问的代码。在此设置下,Unity 优先考虑减小尺寸而不是代码稳定性,并删除尽可能多的代码。此搜索可能比较低的剥离级别花费更长的时间。仅对紧凑构建大小极其重要的项目使用此设置。彻底测试您的应用程序并谨慎使用[Preserve]属性和 link.xml 文件,以确保 Unity 链接器不会剥离重要代码。 |
Tips: 等级越高裁剪掉的代码越多, 包体也就越小, 但是对应的风险也就更大:
4.强制保留代码
4.1 使用[Preserve]标签
可以对Assembly、Type、Field、Properties、Method使用。
4.2 使用Link.xml文件
在项目的Assets目录下创建个link.xml
保留整个程序集dll:
<?xml version="1.0" encoding="UTF-8"?>
<linker><assembly fullname="DOTween" preserve="all" /> <!-- 保留 DOTween --><assembly fullname="Newtonsoft.Json" preserve="all" /> <!-- 保留 Newtonsoft.Json --><assembly fullname="Assembly-CSharp" preserve="all" /> <!-- 保留我们写的项目代码 -->
</linker>
保留某个程序集里的某个类:
<assembly fullname="UnityEngine"><type fullname="UnityEngine.SpriteRenderer" preserve="all"/><type fullname="UnityEngine.Rigidbody2D" preserve="all"/>
</assembly>
5.Strip中遇到的问题及解决方法
1. 类型转换错误
InvalidCastException: Unable to cast object of type ‘BehaviourTree’ to type ‘DialogueTree’.
对于该类型错误,无法有效的确定错误原因(以NodeCanvas为例,对错误的实例进行类型转换的逻辑流程无法准确定位,可能与NodeCanvas对行为树资源反序列化的实现有关),最直接的办法是将整个模块的Namespace包含到link中以避免此类问题。
(同时可以对官方示例进行同等级的strip,尝试更仔细的解决问题,通常官方示例因为体量小,能更快的进行build迭代和测试)。
2. 无法为抽象类创建对象
Exception: Cannot create an instance of an interface or abstract type for NodeCanvas.Framework.ActionTask。
通常原因在于其实现类没有被保留下来。报错定位依然不明确。解决办法同上。
3. 无法解析符号
Type with name ‘NodeCanvas.Tasks.Actions.PlayerActions.AnimationAction’ could not be resolved.
其中指出的符号,即类型、方法、属性等,因为没有被保留下来,导致进行反射调用时无法确定符号意义导致的问题。解决方法很明确,就是将符号写入link.xml以在strip过程中保留。
**4. 找不到Class ID对应的类型
ReportException: UnityLogError Could not produce class with ID 134.
通常是因为Unity引擎的代码被Strip掉了,导致在程序运行时找不到对应的类。对此类问题比较方便的一点在于,错误信息给出了具体的类(https://docs.unity3d.com/Manual/ClassIDReference.html),要解决问题只需要将查表找到的Class加入到link.xml即可。
6.注意事项
link.xml配置是根据程序集而不是根据名字空间
,例如UnityEngine.Animator,在VisualStudio中跳转到Animator类会发现,它是属于UnityEngine.AnimationModule程序集,而不是UnityEngine程序集。如果配置到错误的程序集自然就不能正确保留该类防止被裁剪。
如保留Animator类,如下方式是无效的:
<assembly fullname="UnityEngine" preserve="all"/>
正确方式应该是:
<assembly fullname="UnityEngine.AnimationModule" preserve="all"/>
Unity项目Build后会在项目Library的子目录,如Library\Bee\artifacts\Android\ManagedStripped下生成项目依赖(没用上的会被裁剪)的全部程序集
(不同版本Unity或不同平台生成程序集位置不同),这样就可以确定需要保留哪些程序集。
il2cpp代码裁剪(Strip Engine Code)配置工具:https://blog.csdn.net/final5788/article/details/126451377
相关文章:

Unity 代码裁剪(Strip Engine Code)
文章目录 0.IL2CPP 打包运行闪退问题1.什么是代码裁剪2.为什么要使用代码裁剪3.代码裁剪设置与级别4.强制保留代码4.1 使用[Preserve]标签4.2 使用Link.xml文件 5.Strip中遇到的问题及解决方法6.注意事项 0.IL2CPP 打包运行闪退问题 Google Play要求从2019年8月1日起apk必须支…...

单目3d重建DUSt3R 笔记
目录 DUSt3R 三维重建 报错RecursionError: maximum recursion depth exceeded in comparison 报错 numpy.core.multiarray failed to import 报错Numpy is not available 解决 升级版mast3r 速度变慢 修改了参数设置脚本: 测试效果 操作技巧 DUSt3R 三维重…...

AI驱动TDSQL-C Serverless 数据库技术实战营-与AI的碰撞
目录 一、简介 二、实验介绍 三、结果展示 四、实操指导 4.1 系统设计 4.2 环境搭建(手把手教程) 4.3 应用构建 4.4 效果展示 4.5 踩坑避雷总结 五、清理资源 5.1 删除TDSQL-C Serverless 5.2 删除 HAI 算力 六、实验总结归纳 一、简介 本…...

C++之String类(上)
片头 嗨!好久不见~ 今天我们来学习C的Sting类,不过,在学习它之前,我们先来对STL库有一个简单的了解。 STL(standard template library--标准模板库),是C标准库的重要组成部分,不仅是…...

kubernets基础-ingress详细介绍
文章目录 什么是IngressIngress详细说明Ingress示例 Ingress控制器Ingress控制器的工作原理Ingress控制器的特点常见的Ingress控制器 Ingress关联Ingress控制器一、Ingress资源对象二、Ingress控制器三、Ingress与Ingress控制器的关联方式四、注意事项 多实例部署一、Ingress多…...

jenkins部署Maven和NodeJS项目
在 Java 项目开发中,项目的编译、测试、打包等是比较繁琐的,属于重复劳动的工作,浪费人力和时间成本。以往开发项目时,程序员往往需要花较多的精力在引用 jar 包搭建项目环境上,跨部门甚至跨人员之间的项目结构都有可能…...
在unity资源中发现无效引用
本文主要解决在不打开unity的情况下搜索出无效引用的资源的方法 1. 概述 一般只要遍历一下目录里所有资源,判空一下就好了但有些情况下,不希望打开unity, 尤其希望是在资源整合时,想更快验证资源的合法性, 这对合并提交及出包验证时,都要较大的需求 2. 简单的验证方法 简单来…...

C#知识|基于反射和接口实现抽象工厂设计模式
哈喽,你好啊,我是雷工! 01 应用场景 在项目的多数据库支持上、业务的多算法封装、以及各种变化的业务中; 02 抽象工厂组成 抽象工厂包括抽象产品(即业务接口,可以通过抽象类或抽象接口设计)…...
【分布式微服务云原生】gRPC vs RPC:深入探索远程过程调用的现代与经典
摘要 在分布式系统的世界里,gRPC和RPC是两个耳熟能详的术语,但它们之间有何区别和联系?本文将深入探讨gRPC和RPC的概念、关键特性、以及它们在现代软件开发中的应用。你将了解到gRPC如何作为RPC的一种实现,提供高性能的跨语言远程…...
听说这是MATLAB基础?
MATLAB(矩阵实验室)是一个强大的高性能计算环境和编程语言,广泛应用于数学计算、算法开发、数据分析、可视化以及模拟等多个领域。以下是MATLAB的一些基础知识,涵盖其功能、语法、基本操作等方面。 1. MATLAB环境 工作区…...

【CSS/HTML】圣杯布局和双飞翼布局实现两侧宽度固定,中间宽度自适应及其他扩展实现
前沿简介 圣杯布局和双飞翼布局是前端重要的布局方式。两者的功能相同,都是为了实现一个两侧宽度固定,中间宽度自适应的三栏布局。 圣杯布局来源于文章In Search of the Holy Grail,双飞翼布局来源于淘宝UED。 两者的实现方式有差异,但是都…...

数据流和数据流处理技术
一数据流 首先明确数据流概念:数据流是连续不断生成的、快速变化的无界数据序列 数据流类型: 数据流大致可以分为四种类型 1.连续型数据流:不断地产生数据,数据稳定速度输入系统。 2.突发型数据流:在某特定时间或…...

(IDEA)spring项目导入本地jar包方法和项目打包时找不到引入本地jar包的问题解决方案
系列文章目录 文章目录 系列文章目录一、(IDEA)spring项目导入本地jar包方法和项目打包时找不到引入本地jar包的问题解决方案1.资料 一、(IDEA)spring项目导入本地jar包方法和项目打包时找不到引入本地jar包的问题解决方案 1.资料…...

解决TikTok无网络连接问题解析
随着社交媒体的快速发展,TikTok已成为全球用户最喜欢的短视频平台之一,吸引了数以亿计的用户。然而,在享受这个平台时,用户经常会遇到无网络连接的问题,这不仅影响观看体验,还可能导致无法上传内容或参与社…...

k8s中,ingress的实现原理,及其架构。
图片来源:自己画的 图片来源:k8s官网 首先,什么是ingress? 是服务还是控制器? 都不精确 ingress是一个api资源 service和deployment也是api资源。 这几个相互协作,组建成一个对外提供服务的架构。 ingress提供的…...

【数据结构强化】应用题打卡
应用题打卡 数组的应用 对称矩阵的压缩存储 注意: 1. 2.上三角的行优先存储及下三角的列优先存储与数组的下表对应 上/下三角矩阵的压缩存储 注意: 上/下三角压缩存储是将0元素统一压缩存储,而不是将对角线元素统一压缩存储 三对角矩阵的…...
解决 MySQL 服务无法启动:failed to restart mysql.service: unit not found
目录 前言1. 问题描述2. 问题分析3. 解决步骤3.1 检查 MySQL 服务文件3.2 备份旧的服务文件3.3 启动 MySQL 服务3.4 验证服务状态 4. 总结结语 前言 在日常使用 MySQL 数据库时,有时候可能会遇到服务无法正常启动的问题。这类问题通常出现在系统更新或者服务配置文…...
Dubbo和Http的调用有什么区别
背景 我们在项目开发中,需要进行调用外部接口时,往往使用Dubbo和Http方式都能实现远程调用。那么他们在使用上,有什么区别呢? 定位不同 一个是分布式环境下的框架,一个是通信协议。 Dubbo:是一种高性能的…...

ARM 架构、cpu
一、ARM的架构 ARM是一种基于精简指令集(RISC)的处理器架构. 1、ARM芯片特点 ARM芯片的主要特点有以下几点: 精简指令集:ARM芯片使用精简指令集,即每条指令只完成一项简单的操作,从而提高指令的执行效率…...
【React】入门Day03 —— Redux 与 React Router 核心概念及应用实例详解
1. Redux 介绍 // 创建一个简单的Redux store const { createStore } Redux;// reducer函数 function counterReducer(state { count: 0 }, action) {switch (action.type) {case INCREMENT:return { count: state.count 1 };case DECREMENT:return { count: state.count -…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...
字符串哈希+KMP
P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...