unity跨平台原理

         一直以来很好奇,为什么unity可以跨平台开发,用了这么久还是有必要弄清楚的,所以今天特地研究了一下,记录下来,也供大家学习。

Unity介绍:

Unity3D主要包括两个部分:Unity EngineUnity Editor。提供了UnityEngine.dll和UnityEditor.dll两个动态库。

Unity Engine:C/C++编写,由平台相关代码,图形API、物理引擎、灯光、网络层接口等组成,编译为UnityEngine.dll,各平台不同,用户Shader代码也属于这一层的内容;

Unity Editor:IDE工具,大部分是由C#编写,插件也是用C#编写(调用UnityEditor.dll开发),用户脚本可用C#/JS/Boo编写,项目代码最后由Mono编译。

 

Mono介绍:

        Mono是一个由Xamarin公司所赞助的开源项目。它基于通用语言架构(Common Language Infrastructure ,缩写为CLI)和C#的ECMA 标准(Ecma-335、Ecam-334),提供了微软的.Net框架的另一种实现。与微软的.Net框架不同的是,Mono具备了跨平台的能力,也就是说它不仅能运行在Windows系统上,而且还可以运行在Mac OSX、Linux甚至是一些游戏平台上。

Mono主要有以下部分组成:

  1. C#编译器——mcs
  2. 运行时:即时编译器JIT 与AOT。以及GC,类库加载器等等。
  3. 基础类库(BCL)
  4. Mono类库。提供了超出微软.NET的一些类,提供了许多额外功能,主要是用于构建其他操作系统上的应用

 

Unity与mono的交互:

        众所周知的一点是,Unity3D游戏引擎本身是用C/C++写成的,将你的Mono运行时嵌入到unity之后,我们的应用就获取了一个完整的虚拟机运行环境。而这一步需要将“libmono”和应用链接,一旦链接完成, 我们再将Mono运行时初始化,一旦Mono运行时初始化成功,那么下一步最重要的就是将CIL代码加载进来,之后就可以解释执行C#代码了。

//链接方式:在unity c++中初始化
#include <mono/metadata/mono-config.h>

MonoDomain* domain;
//mono_jit_init这个方法会返回一个MonoDomain,用来作为盛放托管代码的容器。
//其中的参数managed_binary_path,即应用运行域的名字。
domain = mono_jit_init(managed_binary_path);

CIL介绍:

        CIL(Common Intermediate Language通用中间语言,也叫做MSIL微软中间语言)是一种代码指令集,CIL可以在任何支持CLI(Common Language Infrastructure,通用语言基础结构)的环境中运行,就像.NET是微软对这一标准的实现,Mono则是对CLI的又一实现。由于CIL能运行在所有支持CLI的环境中,那么就和和具体的平台或者CPU无关。这样就无需根据平台的不同而部署不同的内容了。

 

跨平台原理:

        

  • MCS编译器:Mono中C#编译器,是mcs把C#编译为dll(IL代码集合)。
  • JIT编译:或者又称为动态编译,将IL代码转为对应平台原生码(Native Code)并且将原生码映射到虚拟内存中执行。JIT编译的时候IL是在依托Mono运行时,转为对应的原生码后在依托本地运行。但它同时也会将编译过的代码进行缓存,而不是每一次都进行编译。所以说它是静态编译和解释器的结合体。
  • AOT编译:在程序运行之前,先把部分dll中的IL代编译为原生码(Native Code)

因此从上面可以看出unity跨平台的原理:使用mcs把c#(或者js)翻译成IL并生成dll或者exe,应用在平台执行时,先载入mono运行时,mono通过JIT,AOT将IL转成Native Code,然后运行在对应平台上。换言之mono运行的其实IL语言,IL也并非真正的在本地运行,而是在mono运行时中运行的,运行在本地的是被编译后生成的原生码。

IOS的IL2CPP:

        使用Mono的时候,脚本的编译运行如下图所示:

        简单的来说,3大脚本被编译成IL,在游戏运行的时候,IL和项目里其他第三方兼容的DLL一起,放入Mono VM虚拟机,由虚拟机解析成原生码,并且执行。但是使用IL2CPP将会增加一些步骤如下:

        在得到中间语言IL后,使用IL2CPP将他们重新变回C++代码,然后再由各个平台的C++编译器直接编译成能执行的原生汇编代码。

好处:

  • 对于iOS平台,由于不允许运行时生成Native Code,因为ios被禁止了jit,因此上面方式采用Full-AOT的模式,利用IL2CPP将所有IL先转成C++ Code,而C++是可以跨平台编译执行的,因此有效的解决的ios问题。
  • 根据官方的实验数据,换成IL2CPP以后,程序的运行效率有了1.5-2.0倍的提升。
  • 可以利用现成的在各个平台的C++编译器对代码执行编译期优化,这样可以进一步减小最终游戏的尺寸并提高游戏运行速度。
  • 由于动态语言的特性,他们多半无需程序员太多关心内存管理,所有的内存分配和回收都由一个叫做GC(Garbage Collector)的组件完成。虽然通过IL2CPP以后代码变成了静态的C++,但是内存管理这块还是遵循C#的方式,这也是为什么最后还要有一个 IL2CPP VM的原因:它负责提供诸如GC管理,线程创建这类的服务性工作。但是由于去除了IL加载和动态解析的工作,使得IL2CPP VM可以做的很小,并且使得游戏载入时间缩短。

 

 

参考:

 

  • 9
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Unity3D 是一款跨平台游戏开发引擎,其原理可以简单分为以下几方面: 1. 游戏对象与组件:Unity3D 中的所有元素都是以游戏对象(GameObject)的形式存在,游戏对象可以通过添加不同的组件(Component)来赋予其功能和行为。 2. 场景与层级:游戏中的场景(Scene)是一个虚拟的环境,包含了一系列的游戏对象。在场景中,游戏对象的层级(Hierarchy)决定了它们的父子关系和渲染顺序。 3. 渲染管线:Unity3D 使用了基于物理的渲染管线,包括几何渲染、光照计算、材质渲染等过程,通过将场景中的模型、纹理、材质等进行组合和处理,最终呈现出逼真的图像效果。 4. 脚本编程:Unity3D 使用 C# 作为主要的编程语言,开发者可以通过编写脚本来实现游戏逻辑和交互。脚本可以附加到游戏对象上,并通过事件、更新循环等方式来控制对象的行为。 5. 物理引擎:Unity3D 内置了物理引擎,可以模拟现实世界中的物理效果,例如重力、碰撞、刚体等。开发者可以通过设置物理属性和添加碰撞器组件来实现游戏对象之间的物理交互。 总的来说,Unity3D 通过提供一个开发环境和一系列的功能模块,使开发者能够快速创建、设计和发布游戏。它的核心原理是基于游戏对象和组件,通过脚本编程和渲染管线实现游戏的逻辑和图像渲染,同时还提供了物理引擎和其他辅助功能来增强游戏的真实感和交互性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值