当前位置: 首页 > news >正文

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.为什么要使用代码裁剪

  1. 显著减小包体大小:开启代码裁剪,在build时将项目中没有用到的代码裁减掉,以减少build出的代码量
  2. 加快cpp生成的过程:如果使用了il2cpp,由于build过程中先生成CIL然后再生成cpp代码。所以开启代码裁减之后,能减少CIL的生成,从而加快cpp生成的过程。

3.代码裁剪设置与级别

File->Build Settings->Player Settings->Optimization->Managed Stripping Level

属性功能
DisabledUnity 不会删除任何代码。此设置仅可见,并且是使用 Mono 脚本后端时的默认设置。
MinimalUnity 仅在 UnityEngine 和 .NET 类库中搜索未使用的代码。Unity 不会删除任何用户编写的代码。此设置最不可能导致任何意外的运行时行为。此设置对于可用性比构建大小更重要的项目很有用。如果您使用 IL2CPP 脚本后端,这是默认设置。
LowUnity 会搜索部分用户编写的程序集以及所有 UnityEngine 和 .NET 类库以查找未使用的代码。此设置会应用一组规则,删除部分未使用的代码,但会将出现意外后果的可能性降至最低,例如使用反射的运行时代码的行为发生变化。
MediumUnity 会部分搜索所有程序集以查找无法访问的代码。此设置应用一组规则,可删除更多类型的代码模式以减小构建大小。虽然 Unity 不会删除所有可能无法访问的代码,但此设置确实会增加不良或意外行为更改的风险。
HighUnity 会对所有程序集进行广泛搜索,以查找无法访问的代码。在此设置下,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 速度变慢 修改了参数设置脚本&#xff1a; 测试效果 操作技巧 DUSt3R 三维重…...

AI驱动TDSQL-C Serverless 数据库技术实战营-与AI的碰撞

目录 一、简介 二、实验介绍 三、结果展示 四、实操指导 4.1 系统设计 4.2 环境搭建&#xff08;手把手教程&#xff09; 4.3 应用构建 4.4 效果展示 4.5 踩坑避雷总结 五、清理资源 5.1 删除TDSQL-C Serverless 5.2 删除 HAI 算力 六、实验总结归纳 一、简介 本…...

C++之String类(上)

片头 嗨&#xff01;好久不见~ 今天我们来学习C的Sting类&#xff0c;不过&#xff0c;在学习它之前&#xff0c;我们先来对STL库有一个简单的了解。 STL&#xff08;standard template library--标准模板库&#xff09;&#xff0c;是C标准库的重要组成部分&#xff0c;不仅是…...

kubernets基础-ingress详细介绍

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

jenkins部署Maven和NodeJS项目

在 Java 项目开发中&#xff0c;项目的编译、测试、打包等是比较繁琐的&#xff0c;属于重复劳动的工作&#xff0c;浪费人力和时间成本。以往开发项目时&#xff0c;程序员往往需要花较多的精力在引用 jar 包搭建项目环境上&#xff0c;跨部门甚至跨人员之间的项目结构都有可能…...

在unity资源中发现无效引用

本文主要解决在不打开unity的情况下搜索出无效引用的资源的方法 1. 概述 一般只要遍历一下目录里所有资源,判空一下就好了但有些情况下,不希望打开unity, 尤其希望是在资源整合时,想更快验证资源的合法性, 这对合并提交及出包验证时,都要较大的需求 2. 简单的验证方法 简单来…...

C#知识|基于反射和接口实现抽象工厂设计模式

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 01 应用场景 在项目的多数据库支持上、业务的多算法封装、以及各种变化的业务中&#xff1b; 02 抽象工厂组成 抽象工厂包括抽象产品&#xff08;即业务接口&#xff0c;可以通过抽象类或抽象接口设计&#xff09;…...

【分布式微服务云原生】gRPC vs RPC:深入探索远程过程调用的现代与经典

摘要 在分布式系统的世界里&#xff0c;gRPC和RPC是两个耳熟能详的术语&#xff0c;但它们之间有何区别和联系&#xff1f;本文将深入探讨gRPC和RPC的概念、关键特性、以及它们在现代软件开发中的应用。你将了解到gRPC如何作为RPC的一种实现&#xff0c;提供高性能的跨语言远程…...

听说这是MATLAB基础?

MATLAB&#xff08;矩阵实验室&#xff09;是一个强大的高性能计算环境和编程语言&#xff0c;广泛应用于数学计算、算法开发、数据分析、可视化以及模拟等多个领域。以下是MATLAB的一些基础知识&#xff0c;涵盖其功能、语法、基本操作等方面。 1. MATLAB环境 工作区&#xf…...

【CSS/HTML】圣杯布局和双飞翼布局实现两侧宽度固定,中间宽度自适应及其他扩展实现

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

数据流和数据流处理技术

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

(IDEA)spring项目导入本地jar包方法和项目打包时找不到引入本地jar包的问题解决方案

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

解决TikTok无网络连接问题解析

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

k8s中,ingress的实现原理,及其架构。

图片来源&#xff1a;自己画的 图片来源&#xff1a;k8s官网 首先&#xff0c;什么是ingress? 是服务还是控制器&#xff1f; 都不精确 ingress是一个api资源 service和deployment也是api资源。 这几个相互协作&#xff0c;组建成一个对外提供服务的架构。 ingress提供的…...

【数据结构强化】应用题打卡

应用题打卡 数组的应用 对称矩阵的压缩存储 注意&#xff1a; 1. 2.上三角的行优先存储及下三角的列优先存储与数组的下表对应 上/下三角矩阵的压缩存储 注意&#xff1a; 上/下三角压缩存储是将0元素统一压缩存储&#xff0c;而不是将对角线元素统一压缩存储 三对角矩阵的…...

解决 MySQL 服务无法启动:failed to restart mysql.service: unit not found

目录 前言1. 问题描述2. 问题分析3. 解决步骤3.1 检查 MySQL 服务文件3.2 备份旧的服务文件3.3 启动 MySQL 服务3.4 验证服务状态 4. 总结结语 前言 在日常使用 MySQL 数据库时&#xff0c;有时候可能会遇到服务无法正常启动的问题。这类问题通常出现在系统更新或者服务配置文…...

Dubbo和Http的调用有什么区别

背景 我们在项目开发中&#xff0c;需要进行调用外部接口时&#xff0c;往往使用Dubbo和Http方式都能实现远程调用。那么他们在使用上&#xff0c;有什么区别呢&#xff1f; 定位不同 一个是分布式环境下的框架&#xff0c;一个是通信协议。 Dubbo&#xff1a;是一种高性能的…...

ARM 架构、cpu

一、ARM的架构 ARM是一种基于精简指令集&#xff08;RISC&#xff09;的处理器架构. 1、ARM芯片特点 ARM芯片的主要特点有以下几点&#xff1a; 精简指令集&#xff1a;ARM芯片使用精简指令集&#xff0c;即每条指令只完成一项简单的操作&#xff0c;从而提高指令的执行效率…...

【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 -…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...