Unity3D将来时:IL2CPP(下)

转载地址:http://www.game798.com/site/news_detail/id/1580

版本准备
前文详细的介绍了IL2CPP的来龙去脉,这里用一个实际的例子来看看Unity3D里的IL2CPP都为我们做了哪些工作以及在使用的过程中会遇到哪些问题。
IL2CPP应用的第一个平台是WebGL,为了让游戏可以一键部署到基于WebGL的浏览器中,Unity3D Script工作组的大牛们找到了一个绝妙的解决方案:不仅解决了C#,Unity Script语言兼容问题,还解决了客户端源码泄漏问题。这个功能在Unity5.0 Beta版中提供了测试。
IL2CPP的第二个试用平台是iOS 64位版。大家都知道苹果已经发了最后通牒,全新App必须在15年2月1日支持64位CPU,而已经上架的游戏也必须在15年6月1日更新的时候支持64位。这个64位编译就是交由IL2CPP完成的。具体到版本是 Unity 4.6.1 p5,Unity4.6.2和Unity 4.6.2 p1。本文后面都使用4.6.2 p1版本来进行演示。
创建项目,加入代码
创建一个空的项目,加入两个cs文件,一个叫IL2CPPCompatible.cs,另外一个是IL2CPPStudy.cs。前者主要用来测试代码在IL2CPP中的兼容性,后者用来产生C++代码,用来做对比分析。
以下是两个文件的详细内容:
IL2CPPCompatible.cs
这个文件中有两个兼容性测试函数。一个函数使用ThreadPool.QueueUserWorkItem启动一个新的线程。另一个则是SSL认证函数:ssl.AuthenticateAsClient (hosturl); 之所以写这两个函数是因为上述4.6.x IL2CPP对他们支持的还不是很好,会产生问题,这个我们在后面会详细讲到。
IL2CPPStudy.cs
using UnityEngine;
using System.Collections;
using System.IO;
using System.Threading;
public class CoconutClassStudy
{
        public int inta;
        public int intb;
        public int Add()
        {
                return inta + intb;
        }
        public CoconutClassStudy(int a, int b)
        {
                inta = a;
                intb = b;
        }
        public void IOTest(string filename)
        {
                if (File.Exists (filename)) {
                        FileStream fs = File.Open(filename, FileMode.Create);
                        fs.Close();
                }
        }
        public void ThreadTest()
        {
                Thread a =new Thread(delegate(object state) {
                        Debug.Log ("Thread Started");
                });
               
                a.Start ();
        }
}
public class IL2CPPStudy : MonoBehaviour {
        // Use this for initialization
        void Start () {
                Debug.Log (CoconutFuncStudy (10 , 20));
                CoconutClassStudy cc = new CoconutClassStudy (50, 60);
                Debug.Log (cc.Add ());
                cc.IOTest("test.txt");
                cc.ThreadTest ();
                Debug.Log (cc.GetType ());
        }
        
        // Update is called once per frame
        void Update () {
        
        }
        int CoconutFuncStudy(int a, int b)
        {
                return a + b;
        }
}
这个文件里面的内容就更简单了:一个CoconutClassStudy类,里面有一个构造函数,一个Add函数和一个IOTest函数。另外在MonoBehaviour的Start()中,创建这个类的实例,并调用这两个函数。这个源码可以让我们研究以下几个方面:
1.cs的类在经过IL2CPP以后如何在CPP文件中表达
2.C#的IO操作经过IL2CPP以后如何在CPP文件中表达
3.当调用new关键字在堆里产生一个实例的时候CPP文件又是如何做的
4.开启一个线程的操作IL2CPP会如何翻译
5.调用cc.GetType()的行为IL2CPP如何处理
有了这连个文件后我们要做的第一件事情是生成XCode项目:
选择IL2CPP编译模块,然后Build,生成XCode项目。
打开项目,在项目结构中打开Classes目录,可以看到多了一个Native的子目录
IL2CPP转换出的所有文件都在其中。
我们写的逻辑代码,都在Assembly-CSharp.cpp中,除了这个文件,Native文件夹中还有很多以Bulk开头的文件,这些其实是IL2CPP把一些必要C#库翻译到CPP形成的文件。
像Bulk_Generics_x.cpp和System.Collections.Generic有关。
Bulk_UnityEngine.UI_x.cpp则和Unity自带的UI有关。
让我们粗略的分析下在CPP文件中前面的5条都是如何实现的:
1.cs的类在经过IL2CPP以后如何在CPP文件中表达

我们的CoconutClassStudy类在CPP文件中变成了一个Struct,继承于Object_t4。那这个Object_t4又是什么呢?
聪明的你一看注释就知道了吧,没错,这个就是C#中的万物之源,System.Object。
既然我们C#的类变成了Struct,那类里面的函数都去哪里了呢?带着这个疑问,我们来看第二条。
2.C#的IO操作经过IL2CPP以后如何在CPP文件中表达
在CoconutClassStudy类中有一个成员函数:IOTest。在CPP中,我们看到了如下的实现:
类中的函数变成了一般的全局函数,函数名字是类名加上函数名,最后加上一个后缀而成。而原本C#中的File.Exists和File.Open函数都有了相应的C++实现。
3.当调用new关键字在堆里产生一个实例的时候CPP文件又是如何做的?
C#代码中我们在Start函数中有一个显示的New,找到相应C++代码:
可以看到代码调用了一个叫il2cpp_codegen_object_new的函数。而这个函数最终调用了IL2CPP VM中的New函数,分配了属于GC管理的内存。
接下来第四条
4.开启一个线程的操作IL2CPP会如何翻译
C#中的System.Thread,在C++中是一个Thread_t26相当巨大的结构,在New出了这个结构之后,设置线程入口函数,最后调用Thread_Start_m47启动线程。这个函数就是对应System.Threading.Thread.Start()

        我们看最后一条
5.调用cc.GetType()的行为IL2CPP如何处理。找到C++中的对应Start函数:
首先我们看到了对应C#中的Type的C++实现:Type_t28,其次是GetType()这个函数在C++中的实现,最后发现是调到了IL2CPP的VM函数:

在这些C++的实现中,细心的读者可能会发现他们时时刻刻都在使用MethodInfo和TypeInfo这样的信息。这个就是Unity Script项目组提到的Metadata。Metadata指的是非逻辑代码,而是函数,结构,变量以及类本省的一些信息。比如名字,类型等。这个Metadata提供C++代码和后台的IL2CPP VM运行时必要的信息。
以上5条只是很简单的例子,大家如果对IL2CPP的转换感兴趣,可以自己写出想要了解的测试代码,然后再对比CPP文件看其实现。
前方有坑,请小心
新的事物总是伴随着问题,特别是在软件行业,Bug是不可避免的。就目前阶段而言,IL2CPP还有不少问题。这个就是项目中IL2CPPCompatible.cs存在的意义:做兼容性测试。大家在实际的项目中如果遇到了问题,可以在这个文件中追加测试代码。下面的表格把我们遇到的已知问题做一个列举,供参考。
 
链接可执行文件zlib报错
ThreadPool.QueueUserWorkItem运行报错
SSL.AuthenticateAsClient运行报错
 
Unity 4.6.1 p5
发生
发生
发生
 
Unity 4.6.2 f1
发生
发生
发生
 
Unity 4.6.2 p1
修正
修正
发生
 
         
IL2CPP总结以及我们的建议
IL2CPP是Unity核心进行的很重要的进化之一。就现在来看,好处有以下几点:
1.运行速度加快,游戏安装尺寸减小,内存占用降低
2.除了可以Mono调试C#之外,我们又多了一种选择:Native C++ 源码级调试(不知道你们什么感觉,我对Unity C#调试颇有意见,经常连不上调试器,而且调试过程中常常宕机。换成用原生IDE调试C++代码,就爽很多啦)。
3.可以快速的支持新的平台,当然这点对我们关系不大。
带来的问题:
1.由于原来由Mono VM的IL代码全部变成了CPP,导致项目中多了很多CPP代码,编译时间会显著增加。
2.IL2CPP还有各种Bug,可能会导致原来的代码不能很好的编译运行。需要等待Unity版本迭代。
3.鉴于C++静态语言的特性,我们不能使用诸如System.Reflection.Emit这样的动态代码。(C# ATO方式编译)
给使用Unity开发者的建议:
IL2CPP是大势所趋,加上苹果强制使用64位支持,意味着到了6月1号,所有用Unity开发的游戏都要用到新的编译方式。如果你的项目比较大,应该立刻开始尝试IL2CPP,以便发现问题,并开始解决。
本文项目在:

https://github.com/CoconutIslandStudio/IL2CPP_Test

Unity3D将来时:IL2CPP(下)相关推荐

  1. 【转】Unity3D将来时:IL2CPP(上)

    Unity3D想必大家都不陌生,独立游戏制作者们很多人都在用它,甚至一些大公司也用在很商业的游戏制作上.Unity3D最大的一个特点是一次制作,多平台部署,而这一核心功能是靠Mono实现的.可以说Mo ...

  2. Unity3D 在Game窗口下查看Overdraw视图

    overdraw简单来说,就是一个像素在荧幕被绘制了多次. 在像素处理中,overdraw是最常见的性能瓶颈之一. 上个项目中优化过,全屏UI渲染时,游戏主场景在UI后重复绘制,导致完全没有必要的Ov ...

  3. Unity3D在android系统下调试

    一.工具准备 1.JDK--由于android是基于Java平台开发的,jdk是必须要安装的.下载地址:http://www.java.net/download/jdk6/6u10/promoted/ ...

  4. Unity3D研究院之Editor下监听Transform变化

    美术有可以直接在Editor下操作Transform,我想去修正他们编辑的数值,所以我就得监听Transform. C# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  5. 【Unity3D—C#】按下任意按键,返回按键的名称 以及 KeyCode键码详解

    在OnGUI() 函数内使用事件Event方法,可返回按键KeyCode.按一次键会显示两次相同值. void OnGUI()         {             Event e = Even ...

  6. unity3d 非运行模式下执行脚本

    using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; ...

  7. Unity IL2Cpp

    为什么80%的码农都做不了架构师?>>>    编者注 由于之前引入的log4net,在IL2Cpp下无法正常运行,导致没有日志库使用.还需要解决protobuf或thrift是否支 ...

  8. UNITY3D与iOS交互解决方案

    原地址:http://bbs.18183.com/thread-456979-1-1.html 本帖最后由 啊,将进酒 于 2014-2-27 11:17 编辑 "授人以鱼,不如授人以渔&q ...

  9. Unity3D使用经验总结 编辑器扩展篇【转】

    一个引擎,最重要的就是工具,工具除了提升开发速度,提供可视化操作环境以外,还带了容错功能. 它使得大家的工作局限在一定的范围内,比如一个变量的配置,或者是一些类型的选择. 使用编辑器,使得既使不太明白 ...

最新文章

  1. 转载一些关于博客的文章
  2. 柜员计算机技能,新入职柜员必备软件:柜员技能训练系统最新版
  3. Android(java)学习笔记164:开发一个多界面的应用程序之不同界面间互相传递数据(短信助手案例)...
  4. x390拆机_用了七八年的笔记本电脑依然流畅如初,从X230i换到X390
  5. 基于Socket的.NET应用组件
  6. 基于matlab仿真的功率因数测定方法研究,基于MATLAB的单相全控整流电路功率因数测定.pdf...
  7. Python-开根号的几种方式
  8. 计算机后端维护,机房智能交通后台系统运行维护内容.doc
  9. 参考文献标引方式_参考文献标注及排写格式
  10. 软件打包部署神器InnoSetup
  11. c语言魂斗罗小游戏代码,(搬运)魂斗罗系列游戏秘籍(包含一些解锁要数)
  12. Ubuntu 18.04 安装 php7.4 --enable-maintainer-zts
  13. C++11版本后的一写新语法及使用方法for、vector、map
  14. 贝叶斯公式/贝叶斯法则/贝叶斯定理
  15. Android-通讯录
  16. 从RTP包中分析OPUS码流
  17. win10的开机启动目录(文件夹)位置
  18. 202011 网络是通的,数据发不过去(接受不到)
  19. 3000字扫盲shell基础知识(新手必备)
  20. Centos7中语言如何设置成中文

热门文章

  1. 《一笔画问题》解题报告
  2. 犇牛的防御-写给公司的邮件
  3. DSP280049代码迁移DSP280039注意事项
  4. 20:00 @烤仔建工 | 来体验你人生中第一次元宇宙狼人杀鸭~
  5. 安装微软常用运行库合集 解决------由于找不到VCRUNTIME140.dll,无法继续执行代码问题解决
  6. 诊所管理软件_药一点诊所管理系统v2.0.0.1
  7. 有道词典7.2电脑版去广告
  8. 奔驰原厂柏林之声加装 成都蔚一名车汇
  9. 2022最新Let正版短信测压系统源码+全开源版
  10. 面试的时候问:你的期望薪资多少?怎么谈?