Unity跨平台基本原理

目录

前言

​编辑

Mono

Unity和Mono的关系

Unity跨平台必备概念

Mono利用

Mono主要构成部分

基于Mono跨平台的优缺点

IL2CPP

Mono和IL2CPP的区别

Mono

IL2CPP

Mono和IL2CPP的使用建议

安装IL2CPP

IL2CPP打包存在的问题

类型裁剪

泛型问题


前言

        Unity跨平台的基本原理主要基于其底层架构和Mono的运行机制。以下是对Unity跨平台基本原理的详细阐述。

Mono

Unity和Mono的关系

Unity公司于2004年成立。Unity的底层是通过C/C++来完成的,但是为了更方便的让开发者使用,
Mono在当时成为了不二之选,它同时具备跨平台和跨语言的两个特性。

Unity希望能有更多的开发者使用其进行游戏开发,并且一次开发一劳永逸,所以跨语言和跨平台对于他们来说是很重要的。虽然C++本身跨平台,但是如果使用C++作为上层逻辑开发语言,那么作为开发者来说选择性相对较少,并且对于初学者来说学习难度也较大,所以当时的Mono是非常满足Unity需求的不仅支持跨语言还支持跨平台。

Unity跨平台必备概念

Unity主要包括两个部分
Unity Engine(引擎)
包含平台相关代码提供UnityEngine.dll动态库,各平台不同,C/C++编写,图形AP1、物理引擎、灯光等等所有游戏引擎底层内容

Unity Editor(编辑器)
提供UnityEditor.dll动态库,大部分由C#编写,用户脚本最初可以使用C#JavaScript、Boo语言编写,项目代码最后由Mono编译

Mono利用

.Net平台制定的CLI公共语言基础结构规则,利用它我们可以把很多种语言编译成通用规范的CIL公共中间语言,再利用CLR公共语言运行时,将这些CIL公共中间语言转换为对应操作系统的原生代码。
这样用各种不同语言编写的逻辑就能够在指定操作系统上运行了,它的这一套规则是在.Net Framework规则上进行的修改和添加。

Mono主要构成部分

1.C#编译器(mcs)
2.Mono Runtime 类似CLR公共语言运行时(虚拟机)
包括JIT(Just in time)即时编译器、AOT(Ahead of time)提前编译器、GC、类库加载器 等等
3.BCL基础类库
4.Mono类库
提供很多超出.Net的一些额外功能,主要用于构建各种操作系统上的应用

在Unity下使用各种语言进行逻辑实现
这些语言在发布时会被编译成IL中间代码
最终这些中间代码在对应操作系统上
通过Mono VM(虚拟机)真正翻译成机器码运行起来

基于Mono跨平台的优缺点

优点:
只要在不同操作系统上实现MonoVM(虚拟机)
那我们能够支持的平台就会“无限”多

缺点:
维护工作耗时耗力,当Unity版本更新时,MonoVM也需要维护和更新
那多对于N多个平台来说,工作量是非常大的。(Unity的工作量)
低版本Mono无法支持新版本C#的强大新特性


IL2CPP

IL2CPP是在Unity4.6.1 p5之后的版本中加入的脚本后处理方式
你可以把它简单理解为是继Mono之后的一种跨平台解决方案
顾名思义就是把IL中间代码转译为CPP代码(C++)

通过IL2CPP我们可以将编译好的LL中间代码转译成C++代码
再利用各平台优化过的编译器编译为对应平台的目标代码

IL2CPP和Mono的区别就在于当生成了IL中间代码后
Mono是直接通过虚拟机转译运行
而IL2CPP的步骤多了一些
会将儿中间代码转译为C++代码
再通过各平台的C++编译器直接编译为可执行的原生汇编代码

需要注意的是
虽然中间代码变为了C++
但是内存管理还是遵循C#中GC的方式
这也是为什么有一个IL2CPP VM(虚拟机)存在的原因,它主要是用来完成GC管理,线程创建等服务工作的


Mono和IL2CPP的区别

Mono

1.构建(最终打包时)速度快
Oher I DLL

2.Mono编译机制是川T即时编译,所以支持更多类库

3.必须将代码发布为托管程序集(.d文件)

4.Mono VM虚拟机平台维护麻烦,且部分平台不支持(WebGL)

5.由于Mono版本授权原因,C#很多新特性无法使用

6.IOS支持Mono,但不在允许32位的Mono应用提交到应用商店

IL2CPP

1.相对Mono构建(最终打包时)速度慢

2.只支持AOT提前编译

3.可以启用引擎代码剥离来减少代码的大小

4.程序的运行效率比Mono高,运行速度快

5多平台移植更加方便

Mono和IL2CPP的最大区别就是IL2CPP不能在运行时动态生成代码和类型,所以必须在编译时就完全确定需要用到的类型。举例:List<A>和List<B>中A和B是我们自定义的类,我能必须在代码中显示的调用过,IL2CPP才能保留List<A>和List<B>两个类型。如果在热更新时我们调用List<C>,但是它之前并没有在代码中显示调用过,那么这时就会出现报错等问题。主要就是因为川T和AOT两个编译模式的不同造成的。


Mono和IL2CPP的使用建议

由于IL2CPP的运行效率有很大优势,所以建议大家在实际开发中直接使用IL2CPP模式进行打包


安装IL2CPP

编辑器中添加模块选择目标平台带有IL2CPP支持项的。


IL2CPP打包存在的问题

类型裁剪

IL2CPP在打包时会自动对Unity工程的DLL进行裁剪,将代码中没有引用到的类型裁剪掉,以达到减小发布后包的尺寸的目的。然而在实际使用过程中,很多类型有可能会被意外剪裁掉,造成运行时抛出找不到某个类型的异常。特别是通过反射等方式在编译时无法得知的函数调用,在运行时都很有可能遇到问题

解决方案:
1.IL2CPP处理模式时,将PlayerSetting->Other Setting->Managed Stripping Level(代码剥离)设置为Low


Disable:Mono模式下才能设置为不删除任何代码
Low:默认低级别,保守的删除代码,删除大多数无法访问的代码,同时也最大程度减少剥离实际使用的代码的可能性
Medium:中等级别,不如低级别剥离谨慎,也不会达到高级别的极端
Hight:高级别,尽可能多的删除无法访问的代码,有限优化尺寸减小。如果选择该模式一般需要配合link.xml使用

2.通过Unity提供的link.xml方式来告诉Unity引擎,哪些类型是不能够被剪裁掉的
在Unity工程的Assets目录中(或其任何子目录中)建立一个叫link.xml的XML文件

泛型问题

IL2CPP和Mono最大的区别,是不能在运行时动态生成代码和类型。就是说 泛型相关的内容,如果你在打包生成前没有把之后想要使用的泛型类型显示使用一次,那么之后如果使用没有被编译的类型,就会出现找不到类型的报错。

举例:List<A>和List<B>中A和B是我们自定义的类,我们必须在代码中显示的调用过,IL2CPP才能保留List<A>和List<B>两个类型。如果在热更新时我们调用List<C>,但是它之前并没有在代码中显示调用过,那么这时就会出现报错等问题。主要就是因为JIT和AOT两个编译模式的不同造成的。

List<A> list = new List<A>();
List<B> list2 = new List<B>();

 解决方案:
泛型类:声明一个类,然后在这个类中声明一些public的泛型类变量
泛型方法:随便写一个静态方法,在将这个泛型方法在其中调用一下。这个静态方法无需被调用,
这样做的目的其实就是在预言编译之前让IL2CPP知道我们需要使用这个内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/10384.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络(3)

UDP是面向无连接的通信协议&#xff0c;UDP数据包括目的端口号和源端口号信息&#xff0c;由于 不需要连接&#xff0c;所以可以实现广播发送&#xff1b; 传输控制层 UDP协议&#xff08;用户数据报协议&#xff09; UDP通信时不需要接收方确认&#xff0c;属于不可靠的传输&a…

2024年11月8日上海帆软用户大会

2024年11月8日上海帆软用户大会 2024年11月8日&#xff0c;上海成功举办了帆软用户大会&#xff0c;主题为“数字聚力&#xff0c;绽放新机”。大会汇聚了众多行业专家和企业代表&#xff0c;共同探讨数字化转型和商业智能领域的最新趋势和实践。 大会亮点&#xff1a; 专家…

PySimpleGUI和Pymysql

PySimpleGUI 库 PySimpleGUI 是一个用于简化 GUI 编程的 Python 包&#xff0c;它封装了多种底层 GUI 框架&#xff08;如 tkinter、Qt、WxPython 等&#xff09;&#xff0c;提供了简单易用的 API。PySimpleGUI 包含了大量的控件&#xff08;也称为小部件或组件&#xff09;&…

Qt Event事件系统小探1

目录 Qt Event System From qt.doc 如何传递事件 事件类型 事件处理程序 事件过滤器 发送事件 事件的产生和派发 处理我们的事件 来一段好玩的代码 扩展&#xff1a;QWidget如何处理我们的事件&#xff1f; 扩展2&#xff1a;实现一个变色的Label Qt Event System Fr…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于凸多面体仿射变换的用户侧灵活性资源多元聚合方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

vue3组合式API下封装hooks使用生命周期,在await之后调用hooks会有警告

起因&#xff1a;想封装一个hooks实现echarts图表随屏幕大小resize并且组件销毁时移除监听。结果在组件里面调用这个hooks&#xff0c;有个告警提示 [Vue warn]: onBeforeUnmount is called when there is no active component instance to be associated with. Lifecycle inje…

使用Python实现图像的手绘风格效果

使用Python实现图像的手绘风格效果 一、引言二、代码详细解释与示例三、完整框架流程四、运行五、结论附&#xff1a;完整代码 一、引言 在数字图像处理领域&#xff0c;模拟手绘风格是一项有趣且具有挑战性的任务。手绘风格图像通常具有独特的纹理和深浅变化&#xff0c;给人…

window中借助nginx配置vite+vue项目的反向代理步骤

在官网下载好nginx的安装包后&#xff0c;解压后 CMD打开 start nginx 是启动命令 nginx -s stop 停止服务 nginx -s reload 如果重写了nginx.conf文件&#xff0c;要执行这条命令 正常情况下 成功启动和成功停止服务长这样 错误情况&解决 如果nginx -s stop失败 ngi…

花指令例子

如图所示&#xff1a; 指令EB FF的汇编代码为jmp -1&#xff0c;CPU执行到地址处0x6c80c0的指令EB FF时(jmp -1)&#xff0c;EIP为6c80c2, 执行后&#xff0c;EIP为0x6c80c1。但是反汇编器无法自动识别该指令。

关于我的编程语言——C/C++——第八篇

&#xff08;叠甲&#xff1a;如有侵权请联系&#xff0c;内容都是自己学习的总结&#xff0c;一定不全面&#xff0c;仅当互相交流&#xff08;轻点骂&#xff09;我也只是站在巨人肩膀上的一个小卡拉米&#xff0c;已老实&#xff0c;求放过&#xff09; 什么是C C语言是结…

博客园美化

1、主题介绍 使用的 SimpleMemory 这款主题 github官网 2、设置主题并申请 js 代码权限 3、主题设置 博客侧边栏公告 <script type"text/javascript">window.cnblogsConfig {info: {blogIcon: https://ts1.cn.mm.bing.net/th/id/R-C.85775e482741cb7ab7f…

SpringBoot基础系列学习(二):配置详解

文章目录 一丶依赖二丶配置文件三丶获取配置文件中的信息1.PropertySource("classpath:application2.properties")2. ConfigurationProperties(prefix "baicaizhi1")3. Value4. 使用EnviromentgBean获取5. 使用ResourceBundle获取 一丶依赖 <dependen…

初识Electron 进程通信

概述 Electron chromium nodejs native API&#xff0c;也就是将node环境和浏览器环境整合到了一起&#xff0c;这样就构成了桌面端&#xff08;chromium负责渲染、node负责操作系统API等&#xff09; 流程模型 预加载脚本&#xff1a;运行在浏览器环境下&#xff0c;但是…

建网站怎么建?只需几个步骤

在这个网络飞速发展的时代&#xff0c;越来越多的人都渴望拥有自己的网站。然而&#xff0c;对于大多数新手来说&#xff0c;如何建立自己的网站可能充满了挑战。本文将为您详细介绍建网站的关键步骤&#xff0c;让您能够轻松搭建自己的网站。 选择适合的建站工具 虽然市面上有…

台达控制器与三菱变频器实现EtherCAT转CC-Link IEFB协议通讯方案

一.项目背景&#xff1a; 在某自动化生产车间中&#xff0c;原有系统采用台达的 EtherCAT 控制器来控制多个设备的运动和操作&#xff0c;但车间内的一些关键设备使用的是三菱变频器&#xff0c;且基于 CC-Link IEFB 协议通讯。为了实现整个系统的集中控制和数据统一管理&#…

Js — 防抖及底层实现

防抖&#xff1a;单位时间内&#xff0c;频繁触发事件&#xff0c;只执行最后一次 防抖实现方式&#xff1a; lodash提供的防抖函数_.debounce(func,[wait0],[option]) 延迟wait毫秒后调用func方法 定时器setTimeout 目标&#xff1a;鼠标在盒子上移动&#xff0c;鼠标停止50…

负载均衡式在线oj项目开发文档2(个人项目)

judge模块的框架 完成了网页渲染的功能之后&#xff0c;就需要判断用户提交的代码是否是正确的&#xff0c;当用户点击提交之后&#xff0c;就会交给路由模块的/judge模块&#xff0c;然后这个路由模块就需要去调用jude模块了&#xff0c;也就是需要一个新的jude模块&#xff…

setContentView调用流程(二) -将布局添加到mContentParent

Android setContentView执行流程(一)-生成DecorView Android setContentView执行流程(二)-将布局添加到mContentParent 上篇博客我们介绍了setContentView的第一步即生成DecorView以及获取到mContentParent的流程&#xff0c;同时还提到继承自Activity和AppCompatActivity生成…

【C#设计模式(2)——工厂模式】

前言 工厂模式&#xff1a;使用工厂创建对象。工厂模式的主要目的是分离对象的创建与调用&#xff0c;通过使用工厂统一管理对象的创建。工厂模式可以隐藏对象的创建细节&#xff0c;使客户终端代码只关注使用对象而不需要关注对象的创建过程。 运行结果 代码 #region 食品 /…

Dockerfile

1. Dockerfile 简介 1.1 什么是Dockerfile Dockerfile是一个用于定义和构建Docker镜像的文本文件&#xff0c;它通过一系列指令和参数来描述镜像的构建过程和配置。这些指令包括基础镜像、软件包安装、文件拷贝、环境变量设置等&#xff0c;使得应用程序及其依赖项可以被打包…