您的位置:

深入理解il2cpp

一、il2cpp介绍

il2cpp是Unity3D引擎跨平台开发的基础。它是一种将C#或其他.net语言编写的代码转换成C++代码的工具。通过这个工具,Unity3D游戏引擎用户可利用C#及其高效率开发效果,在保证游戏性能的同时保障游戏的跨平台性。

il2cpp的优点是降低了开发成本和提高了游戏性能。Unity3D游戏引擎解释执行C#等高级语言时会引起系统和硬件的瓶颈,降低CPU处理效率和浪费时间,而方式是将C#或其他.net语言编写的代码转换成C++ 代码,执行效率提高了100倍以上。

Il2cpp就像是科学实验室里的魔方,可以执着地拎起各种上课用语言代码进行转换,使结果看上去就像是我们一直以来写的,只是效率更高了。

二、il2cpp的转换过程

实现Unity游戏引擎C#代码到本地代码的转换,使用的是Mono技术。这个技术是一个开源的跨平台的工具,主要提供了一个基于.NET Framework或者.NET Core的虚拟机,使之能够在各种平台上运行。同时,Mono还支持很多的编程语言,如C#、F#、VB、ASP.NET等,并且拥有很强大的跨平台性。在游戏引擎的构建中,Unity特别是重新实现了Mono技术,称为Unity Mono。

利用这两个技术实现C#到C++的转换,首先C#代码需要通过编译器生成IL代码,然后IL代码会被转化为C++代码。to生成C++代码,il2cpp包含诸如类型表、元数据、全局的指令和引用表等数据,并将它们组织成一个能被Visual Studio C++编译器编译的C++代码。

//C#代码
public class HelloWorld
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Hello World");
    }
}
//IL代码
.method public static void  Main() cil managed
{
  // Code size      13 (0xd)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "Hello World"
  IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_000b:  nop
  IL_000c:  ret
}
//C++代码
void HelloWorld::Main(System::String[]* args)
{
    System::Console::WriteLine((System::String*)il2cpp_codegen_object_new((Il2CppObject*)il2cpp_codegen_initialize_runtime_metadata((MethodInfo*)il2cpp_rgctx_method(method->klass->rgctx_data, 0)), il2cpp_rgvargsarray({ 0 })));
}

三、il2cpp编译下的常用工具库

我们可能会在.NET框架中使用一些常用的工具库,它们可以很好地让我们应对各种情况,比如常见的Json与XML序列化/反序列化、AES/CBC加解密、PNG文件处理和TCP/UDP网络通信。在il2cpp编译后,即便我们在编写代码时使用了这些工具库,实际上它们所依赖的库在il2cpp编译以下并没有被包含,这也是一些玩家反映游戏运行缺失库文件的原因。

针对这种情况,我们可以离线导入相应的框架。它们通常有开源的版本,可以自己去Github查找、下载、编译,或者直接在Unity Asset Store中获取。拿到这些框架的代码之后,我们可以打成dll文件,然后让Unity在编译时自动打包。

四、il2cpp优化技巧

在使用il2cpp的过程中,有一些优化技巧可以提高游戏的性能。其中,在使用DotPeek、ILDasm等工具进行反编译的时候,可以看到decompile_as_csharp标签,这个标签可以让转换工具把一个方法转化成可阅读的C#代码。同样,在Unity中可以使用它的API的Conditional标签,这个标签可以在有条件限制下过滤代码,达到优化的结果。

[Conditional("DEBUG")]
void ClearLog()
{
    #if UNITY_EDITOR
    Assembly assembly = Assembly.GetAssembly(typeof(UnityEditor.ActiveEditorTracker));
    Type logEntries = assembly.GetType("UnityEditor.LogEntries");
    MethodInfo clearConsoleMethod = logEntries.GetMethod("Clear");
    clearConsoleMethod.Invoke(new object(), null);
    #endif
}

我们还可以选择性的忽略那些带重复代码的代码段,比如多个地方都要访问同一方法的情况,我们可以将同一个方法分别写到多处,需要的时候调用即可。还有就是可以具体分离出测试代码、生产代码,让生产代码更加纯净、简单,更快地运行和更加稳定。其中,测试代码可针对不同环境、场景、设备等进行系统性的测试、验证,方便我们在开发中随时快速修复漏洞或错误。

五、结论

以上是本文对il2cpp技术的介绍。il2cpp可以将C#代码转换为C++代码,提高游戏的性能和跨平台性。同时,我们需要离线导入依赖库、采取优化技巧等来使得转换后的代码能够更好地应用于游戏运行。在大型游戏开发中,il2cpp的使用对我们有很大的好处。