我的unity ios metal 选项5里,怎么没有IL2CPP选项

& & & & &最初发现这个问题的情况是,当游戏用IL2CPP平台发布IOS版本的时候,会遇到某些dll格式的插件会导致游戏抛异常崩溃,比如FullInspector和Behavior Designer。所抛的异常是找不到某些类的默认构造函数。
&&&&&&&& 后来发现,不只是某些插件会报这种异常,很多json格式的序列化功能也会在IL2CPP平台上抛找不到默认构造函数的异常。
&&&&&&&& 导致这个问题的原因是,IL2CPP版本在AOT编译时的一些优化机制导致的。想要详细了解这个机制的话可以看文档:
&&&&&&&& 其实问题就出在函数的静态调用和利用反射进行动态调用的区别上。在AOT阶段编译的时候,凡是检查到某个类或某个函数完全没有使用到,编译器就会抛弃它。这是一个优化机制,但问题就是这种检查只能检查静态引用,对于利用反射机制进行的调用编译器发现不了。这就导致了,没有进行静态引用的函数,会被编译器抛弃掉,然后在企图通过反射机制进行调用的时候,就会导致找不到要调用的函数。
&&&&&&&& 举个例子,有些序列化插件,比如FullSerializer,在生成新对象的时候没有用new(静态引用),而是用了Activator泛型(动态反射)。所以类的构造函数会在编译的时候抛弃掉,然后Activator企图动态访问其动态函数的时候,问题就出现了。
&&&&&&&& 解决这个问题的方法,比较直接的做法在代码中加入丢失的构造函数的静态引用,也就是随便找个地方new一个出来。这样可以防止IL2CPP在优化的时候被抛弃。这种做法的问题是会留一个无用的对象在内存里。
&&&&&&&& 更好的做法是用Unity3D的link.xml功能。这个link.xml的功能就是在AOT编译的时候,告诉编译器,link.xml里指定的这些类,不管有没有引用到,都要保留下来。虽然可以精确指向到某个类,但是比较简单的做法是,把整个出问题的插件的命名空间全部包含进去就可以了。
&&&&&&&& 举个例子,在对应FullInspector和Behavior Designer的时候,link.xml大概是长这个样子的:
&&&&&& &assembly fullname="FullInspector-Core"&
&&&&&&&&&&&&&& &namespace fullname="FullInspector" preserve="all"/&
&&&&&& &/assembly&
&&&&&& &assembly fullname="BehaviorDesignerRuntime"&
&&&&&&&&&&&&&& & namespace fullname="BehaviorDesigner.Runtime " preserve="all"/&
&&&&&& &/assembly&
&&&&&&&& 这样这两个插件里的类和函数都会被完整的保留下来了,问题解决。
阅读(...) 评论()我的unity 5里,怎么没有IL2CPP选项 ? - 知乎12被浏览3435分享邀请回答0添加评论分享收藏感谢收起Unity将来时:IL2CPP怎么用? - 知乎专栏
{"debug":false,"apiRoot":"","paySDK":"/api/js","wechatConfigAPI":"/api/wechat/jssdkconfig","name":"production","instance":"column","tokens":{"X-XSRF-TOKEN":null,"X-UDID":null,"Authorization":"oauth c3cef7c66aa9e6a1e3160e20"}}
{"database":{"Post":{"":{"contributes":[{"sourceColumn":{"lastUpdated":,"description":"||独立游戏开发者社区,让我们来聊点实际的。","permission":"COLUMN_PUBLIC","memberId":,"contributePermission":"COLUMN_PUBLIC","translatedCommentPermission":"all","canManage":true,"intro":"||独立游戏开发…","urlToken":"indieace","id":4791,"imagePath":"8a94f50b9ef","slug":"indieace","applyReason":"","name":"IndieACE","title":"IndieACE","url":"/indieace","commentPermission":"COLUMN_ALL_CAN_COMMENT","canPost":true,"created":,"state":"COLUMN_NORMAL","followers":3116,"avatar":{"id":"8a94f50b9ef","template":"/{id}_{size}.jpg"},"activateAuthorRequested":false,"following":false,"imageUrl":"/8a94f50b9ef_l.jpg","articlesCount":56},"state":"accepted","targetPost":{"titleImage":"/eab36aea1b7cb3fc2ff94c_r.jpg","lastUpdated":,"imagePath":"eab36aea1b7cb3fc2ff94c","permission":"ARTICLE_PUBLIC","topics":[],"summary":"版本准备 前文详细的介绍了IL2CPP的来龙去脉,这里用一个实际的例子来看看Unity3D里的IL2CPP都为我们做了哪些工作以及在使用的过程中会遇到哪些问题。 IL2CPP应用的第一个平台是WebGL,为了让游戏可以一键部署到基于WebGL的浏览器中,Unity3D Script工作组…","copyPermission":"ARTICLE_COPYABLE","translatedCommentPermission":"all","likes":0,"origAuthorId":,"publishedTime":"T12:07:04+08:00","sourceUrl":"","urlToken":,"id":169987,"withContent":false,"slug":,"bigTitleImage":false,"title":"Unity将来时:IL2CPP怎么用?","url":"/p/","commentPermission":"ARTICLE_ALL_CAN_COMMENT","snapshotUrl":"","created":,"comments":0,"columnId":4791,"content":"","parentId":0,"state":"ARTICLE_PUBLISHED","imageUrl":"/eab36aea1b7cb3fc2ff94c_r.jpg","author":{"bio":"独立游戏开发者","isFollowing":false,"hash":"eb4132dbcc9ef3a0e9cfcdb","uid":96,"isOrg":false,"slug":"yizhimao","isFollowed":false,"description":"本体其实是一只猫(头像即本人)。","name":"小玉","profileUrl":"/people/yizhimao","avatar":{"id":"a9d6a00d321a770c114e3f","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"memberId":,"excerptTitle":"","voteType":"ARTICLE_VOTE_CLEAR"},"id":264182}],"title":"Unity将来时:IL2CPP怎么用?","author":"yizhimao","content":"版本准备前文详细的介绍了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.csusing UnityE\nusing System.C\nusing System.IO;\nusing System.T\npublic class CoconutClassStudy\n{\n
public int Add()\n
return inta +\n
public CoconutClassStudy(int a, int b)\n
public void IOTest(string filename)\n
if (File.Exists (filename)) {\n
FileStream fs = File.Open(filename, FileMode.Create);\n
fs.Close();\n
public void ThreadTest()\n
Thread a =new Thread(delegate(object state) {\n
Debug.Log (\"Thread Started\");\n
a.Start ();\n
}\n}\n\n\npublic class IL2CPPStudy : MonoBehaviour {\n
// Use this for initialization\n
void Start () {\n
Debug.Log (CoconutFuncStudy (10 , 20));\n
CoconutClassStudy cc = new CoconutClassStudy (50, 60);\n
Debug.Log (cc.Add ());\n
cc.IOTest(\"test.txt\");\n
cc.ThreadTest ();\n
Debug.Log (cc.GetType ());\n
// Update is called once per frame\n
void Update () {\n
int CoconutFuncStudy(int a, int b)\n
return a +\n
}\n}\n这个文件里面的内容就更简单了:一个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管理的内存。可以看到代码调用了一个叫il2cpp_codegen_object_new的函数。而这个函数最终调用了IL2CPP VM中的New函数,分配了属于GC管理的内存。接下来第四条4.开启一个线程的操作IL2CPP会如何翻译C#中的System.Thread,在C++中是一个Thread_t26相当巨大的结构,在New出了这个结构之后,设置线程入口函数,最后调用Thread_Start_m47启动线程。这个函数就是对应System.Threading.Thread.Start() 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#中的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存在的意义:做兼容性测试。大家在实际的项目中如果遇到了问题,可以在这个文件中追加测试代码。下面的表格把我们遇到的已知问题做一个列举,供参考。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,以便发现问题,并开始解决。本文项目在:欢迎关注IndieACE微信公众号:IndieAce,可以看到IndieACE定期分享的好内容。需要转载IndieACE的文章请与我们私信联系。","updated":"T04:07:04.000Z","canComment":false,"commentPermission":"anyone","commentCount":3,"collapsedCount":0,"likeCount":16,"state":"published","isLiked":false,"slug":"","isTitleImageFullScreen":false,"rating":"none","titleImage":"/eab36aea1b7cb3fc2ff94c_r.jpg","links":{"comments":"/api/posts//comments"},"reviewers":[],"topics":[],"adminClosedComment":false,"titleImageSize":{"width":680,"height":375},"href":"/api/posts/","excerptTitle":"","column":{"slug":"indieace","name":"IndieACE"},"tipjarState":"inactivated","annotationAction":[],"sourceUrl":"","pageCommentsCount":3,"hasPublishingDraft":false,"snapshotUrl":"","publishedTime":"T12:07:04+08:00","url":"/p/","lastestLikers":[{"bio":"学生","isFollowing":false,"hash":"6b9cd4b27bd4ec220c355","uid":042000,"isOrg":false,"slug":"chen-wen-jie-36-14","isFollowed":false,"description":"","name":"伊藤陈","profileUrl":"/people/chen-wen-jie-36-14","avatar":{"id":"680defee88099fbdf7ca37","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"登山爱好者/程序员/好好学习天天向上","isFollowing":false,"hash":"d01d85bbabb73e981b355dcd","uid":84,"isOrg":false,"slug":"feng-bing-yang-60","isFollowed":false,"description":"","name":"冯炳炀","profileUrl":"/people/feng-bing-yang-60","avatar":{"id":"48e161719","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"3D游戏引擎研发","isFollowing":false,"hash":"01ccd4284af0acbfb19641","uid":478800,"isOrg":false,"slug":"li-qi-72-86","isFollowed":false,"description":"","name":"李琦","profileUrl":"/people/li-qi-72-86","avatar":{"id":"da8e974dc","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":null,"isFollowing":false,"hash":"f3b1fc7e5f","uid":24,"isOrg":false,"slug":"chai-chase","isFollowed":false,"description":"此木为柴","name":"柴chase","profileUrl":"/people/chai-chase","avatar":{"id":"06ace661a","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"图灵的光环/编程的派宗/卡马克的像素/浅色的床单","isFollowing":false,"hash":"2ba6d91eb3c63acd5a02b1","uid":72,"isOrg":false,"slug":"cxihu","isFollowed":false,"description":"搞个大游戏。","name":"Cxihu","profileUrl":"/people/cxihu","avatar":{"id":"v2-f4a4727ebb","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false}],"summary":"版本准备 前文详细的介绍了IL2CPP的来龙去脉,这里用一个实际的例子来看看Unity3D里的IL2CPP都为我们做了哪些工作以及在使用的过程中会遇到哪些问题。 IL2CPP应用的第一个平台是WebGL,为了让游戏可以一键部署到基于WebGL的浏览器中,Unity3D Script工作组…","reviewingCommentsCount":0,"meta":{"previous":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"/50/25abeb581bf1_xl.jpg","links":{"comments":"/api/posts//comments"},"topics":[],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"独立游戏开发者","isFollowing":false,"hash":"eb4132dbcc9ef3a0e9cfcdb","uid":96,"isOrg":false,"slug":"yizhimao","isFollowed":false,"description":"本体其实是一只猫(头像即本人)。","name":"小玉","profileUrl":"/people/yizhimao","avatar":{"id":"a9d6a00d321a770c114e3f","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"column":{"slug":"indieace","name":"IndieACE"},"content":" 作者:Unity3D\n想必大家都不陌生,独立游戏制作者们很多人都在用它,甚至一些大公司也用在很商业的游戏制作上。Unity3D最大的一个特点是一次制作,多平台部署,而\n这一核心功能是靠Mono实现的。可以说Mono是Unity3D核心的核心,是Unity3D跨平台的根本。但是在2014年年中的时\n候,Unity3D官方博客上却发了一篇“”的文章,引出了IL2CPP的概念,感觉有取代Mono之势。那什么是IL2CPP,它能为Unity3D和作为使用Unity3D的我们带来哪些好处和改变?这就是本文尝试说明的。C#,.Net Framework我\n们先说说IL2CPP试图取代的Mono。在说Mono之前,不得不提C#语言和背后的.Net \nFramework。C#是微软推出的一种基于.NET框架的、面向对象的高级编程语言。C#的发音为“see \nsharp”,模仿音乐上的音名“C?”(C调升),是C语言的升级的意思。其正确写法应和音名一样为“C?”。C#由C语言和C++派生而来,继承了其\n强大的性能,同时又以.NET框架类库作为基础,拥有类似Visual \nBasic的快速开发能力。C#由安德斯·海尔斯伯格主持开发,微软在2000年发布了这种语言。说到安德斯·海尔斯伯格这里要多说一句,当年和VC(注\n意,是VC,那个时候还没有Visual
Studio)齐名还有另外一家公司的IDE也非常流行,那就是Borland公司的Delphi,也是由安德斯·海尔斯伯格主导开发的。他\n后来被微软挖走,创建了J++,一门类似Java的语言(好吧,以我肤浅的知识认为,那基本就是照着Java做的)。后来由于和Sun公司授权的原因,微\n软在2001年停止了J++的开发而推出了C# \n1.0。说来要感谢和Sun的这场官司,否则微软也不会有C#,J++也可能一直会跟随Java的脚步。相反C#经过不断的进化,从1.0开始到4.0和\n最新的5.0,C#已经远远甩开Java几条街了(还是以我个人的使用Java和C#感觉而言,关于两门语言的比较,无论是效率上,夸平台上,还是语言易\n用性上,社区活跃度上,网上的争论随处可见,每个人都有自己的看法,这也不是本文的重点)。 Mono,Mono VMC#虽好,但是只能在Windows上运行,微软那时候也没有将其开源,所以总是会有人说不能跨平台,光就这点,C#和Java就不能比呀。微\n软公司已经向ECMA申请将C#作为一种标准。在2001年12月,ECMA发布了ECMA-334 \nC#语言规范。C#在2003年成为一个ISO标准(ISO/IEC 23270)。这意味着只要你遵守CLI(Common Language \nInfrastructure),第三方可以将任何一种语言实现到.Net平台之上。Mono就是在这种环境下诞生的。Mono是一个由\nXamarin公司(先前是Novell,最早为Ximian)所主持的自由开放源代码项目。该项目的目标是创建一系列符合ECMA标准(Ecma-\n334和Ecma-335)的.NET工具,包括C#编译器和通用语言架构。与微软的.NET \nFramework(共通语言运行平台)不同,Mono项目不仅可以运行于Windows系统上,还可以运行于\nLinux,FreeBSD,Unix,OS X和Solaris,甚至一些游戏平台,例如:Playstation 3,Wii或XBox \n360之上。Mono使得C#这门语言有了很好的跨平台能力。相对于微软的.Net Framework运行时库Mono使用自己的Mono \nVM作为运行时库。 加上C#本身快速友好的开发能力,最终使得Unity团队在创建之初就决定将Mono,C#作为其核心。(嗯,这是我猜的)有\n人也许会说,Unity还支持JavaScript和Boo呢,不光光只有C#一门语言。首先我要纠正的是,在Unity中的JavaScript严格意\n义上说并不是W3C规范中的JavaScript,它正确的名字叫做Unity \nScript,其实是从Boo演变过来的(这样大家就能理解为啥在3门语言中,Boo用的人最少,但是却还一直存在的原因了吧)。我认为是Unity开始\n为了让更多的人能够快速的上手,特别是考虑到很多脚本程序员对JavaScript已经很熟悉了,为了照顾这部分人,发明了Unity \nScript,它的语法和W3C的JavaScript几乎一致,使得大家可以直接用其进行开发,降低门槛。但是Unity \nScript在运行上却和JavaScript有着本质的不同。这个我会在下一节IL中进行详细的描述。从三门语言在Unity中的使用情况而言:Boo\n几乎就没人用了,Unity Script和C#两者中无论是演示代码还是Unity Asset \nStore中的第三方代码,C#已经有85%-90%的比例(个人粗略估计,没有做详细统计)。可见C#在Unity中深受我等游戏码农的爱戴。IL啰\n嗦完了C#,.Net Framework和Mono,引出了我们很重要的一个概念”IL“。IL的全称是 Intermediate \nLanguage,很多时候还会看到CIL(Common Intermediate \nLanguage,特指在.Net平台下的IL标准)。在Unity博客和本文中,IL和CIL表示的是同一个东西:翻译过来就是中间语言。它是一种属于\n通用语言架构和.NET框架的低阶(lowest-level)的人类可读的编程语言。目标为.NET框架的语言被编译成CIL,然后汇编成字节码。\nCIL类似一个面向对象的汇编语言,并且它是完全基于堆栈的,它运行在虚拟机上(.Net Framework, Mono VM)的语言。具体过程是:C#或者VB这样遵循CLI规范的高级语言,被先被各自的编译器编译成中间语言:IL(CIL),等到需要真正执行的时候,这些IL会被加载到运行时库,也就是VM中,由VM动态的编译成汇编代码(JIT)然后在执行。正是由于引入了VM,才使得很多动态代码特性得以实现。通过VM我们甚至可以由代码在运行时生成新代码并执行。这个是静态编译语言所无法做到的。回到上一\n节我说的Boo和Unity Script,有了IL和VM的概念我们就不难发现,这两者并没有对应的VM虚拟机,Unity中VM只有一个:Mono \nVM,也就是说Boo和Unity Script是被各自的编译器编译成遵循CLI规范的IL,然后再由Mono VM解释执行的。这也是Unity \nScript和JavaScript的根本区别。JavaScript是最终在浏览器的JS解析器中运行的(例如大名鼎鼎的Google Chrome \nV8引擎),而Unity Script是在Mono \nVM中运行的。本质上说,到了IL这一层级,它是由哪门高级语言创建的也不是那么重要了,你可以用C#,VB,Boo,Unity \nScript甚至C++,只要有相应的编译器能够将其编译成IL都行!IL2CPP, IL2CPP VM本\n文的主角终于出来了:IL2CPP。有了上面的知识,大家很容易就理解其意义了:把IL中间语言转换成CPP文件。大家如果看明白了上面动态语言的\nCLI, \nIL以及VM,再看到IL2CPP一定心中充满了疑惑。现在的大趋势都是把语言加上动态特性,哪怕是c++这样的静态语言,也出现了适合IL的c++编译\n器,为啥Unity要反其道而行之,把IL再弄回静态的CPP呢?这不是吃饱了撑着嘛。根据本文最前面给出的Unity官方博客所解释的,原因有以下几\n个:1.Mono VM在各个平台移植,维护非常耗时,有时甚至不可能完成
Mono的跨平台是通过Mono \nVM实现的,有几个平台,就要实现几个VM,像Unity这样支持多平台的引擎,Mono官方的VM肯定是不能满足需求的。所以针对不同的新平\n台,Unity的项目组就要把VM给移植一遍,同时解决VM里面发现的bug。这非常耗时耗力。这些能移植的平台还好说,还有比如WebGL这样基于浏览\n器的平台。要让WebGL支持Mono的VM几乎是不可能的。2.Mono版本授权受限
\n大家有没有意识到Mono的版本已经更新到3.X了,但是在Unity中,C#的运行时版本一直停留在2.8,这也是Unity社区开发者抱怨的最多一\n条:很多C#的新特性无法使用。这是因为Mono 授权受限,导致Unity无法升级Mono。如果换做是IL2CPP,IL2CPP \nVM这套完全自己开发的组件,就解决了这个问题。3.提高运行效率
根据官方的实验数据,换成IL2CPP以后,程序的运行效率有了1.5-2.0倍的提升。使用Mono的时候,脚本的编译运行如下图所示:简单的来说,3大脚本被编译成IL,在游戏运行的时候,IL和项目里其他第三方兼容的DLL一起,放入Mono VM虚拟机,由虚拟机解析成机器码,并且执行IL2CPP做的改变由下图红色部分标明:
在得到中间语言IL后,使用IL2CPP将他们重新变回C++代码,然后再由各个平台的C++编译器直接编译成能执行的原生汇编代码。几点注意:1.将IL变回CPP的目的除了CPP的执行效率快以外,另一个很重要的原因是可以利用现成的在各个平台的C++编译器对代码执行编译期优化,这样可以进一步减小最终游戏的尺寸并提高游戏运行速度。2.\n由于动态语言的特性,他们多半无需程序员太多关心内存管理,所有的内存分配和回收都由一个叫做GC(Garbage \nCollector)的组件完成。虽然通过IL2CPP以后代码变成了静态的C++,但是内存管理这块还是遵循C#的方式,这也是为什么最后还要有一个\nIL2CPP VM的原因:它负责提供诸如GC管理,线程创建这类的服务性工作。但是由于去除了IL加载和动态解析的工作,使得IL2CPP \nVM可以做的很小,并且使得游戏载入时间缩短。3.由于C++是一门静态语言,这就意味着我们不能使用动态语言的那些酷炫特性。运行时生\n成代码并执行肯定是不可能了。这就是Unity里面提到的所谓AOT(Ahead Of Time)编译而非JIT(Just In \nTime)编译。其实很多平台出于安全的考虑是不允许JIT的,大家最熟悉的有iOS平台,在Console游戏机上,不管是微软的Xbox360, \nXboxOne,还是Sony的PS3,PS4,PSV,没有一个是允许JIT的。使用了IL2CPP,就完全是AOT方式了,如果原来使用了动态特性的\n代码肯定会编译失败。这些代码在编译iOS平台的时候天生也会失败,所以如果你是为iOS开发的游戏代码,就不用担心了。因此就这点而言,我们开发上几乎\n不会感到什么问题。最后给出Unite 2014上官方给出的性能测试截图(数字越小表示运行得越快):有了IL2CPP,程序尺寸可以相对缩小,运行速度可以提高!看了兴奋吗?其实现有的Unity版本中已经引入了IL2CPP技术。本文下篇就通过一个实际的例子,看看IL2CPP都为我们做了哪些,以及我们需要注意些什么。参考链接:欢迎关注IndieACE微信公众号:IndieAce,可以看到IndieACE定期分享的好内容。需要转载IndieACE的文章请与我们私信联系。","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T12:06:58+08:00","url":"/p/","title":"Unity将来时:IL2CPP是什么?","summary":"作者: Unity3D\n想必大家都不陌生,独立游戏制作者们很多人都在用它,甚至一些大公司也用在很商业的游戏制作上。Unity3D最大的一个特点是一次制作,多平台部署,而\n这一核心功能是靠Mono实现的。可以说Mono是Unity3D核心的核心,是Unity3D跨平台的…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":14,"likesCount":81},"next":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"/50/c18f1bca2db1_xl.jpg","links":{"comments":"/api/posts//comments"},"topics":[],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"独立游戏开发者","isFollowing":false,"hash":"eb4132dbcc9ef3a0e9cfcdb","uid":96,"isOrg":false,"slug":"yizhimao","isFollowed":false,"description":"本体其实是一只猫(头像即本人)。","name":"小玉","profileUrl":"/people/yizhimao","avatar":{"id":"a9d6a00d321a770c114e3f","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"column":{"slug":"indieace","name":"IndieACE"},"content":"作者:随着Unity5.0的发布,WebGL平台的部署也正式登场(目前还处于Beta状态)。WebGL是一项利用JavaScript API呈现3D电脑图形的技术。区别于其他需要浏览器加载插件的形式(比如Flash和Unity的Web Player),通过使用WebGL技术,我们只需要编写简单的网页代码即可以实现3D图像在浏览器中的展示。使用WebGL的好处是显而易见的:在玩游戏之前无需下载任何插件,打开浏览器,输入游戏地址,就可以直接进行游戏了。而且WebGL的这套JavaScript API透过浏览器直接和系统的显卡打交道,效率也可以得到保证。WebGL在Unity中的实现具体到技术细节,WebGL在Unity中是通过IL2CPP,Emscripten和asm.js这几大关键技术来实现的。IL2CPP:将脚本代码翻译成C++代码的模块。具体细节在上两篇有详细的讨论(、)这里直接略过。Emscripten:将编译后的Byte Code翻译成Javascript,通过这个步骤以后,代码就可以在浏览器中直接运行了。虽然Emscripten大多数情况下是翻译c/c++的代码(在Unity中的使用情况就是如此),但是它也可以接纳任何由符合LLVM标准的编译器生成的其他语言的Byte Code,将其转换成JavaScript。asm.js:相比前面两个模块,asm.js是最有趣的部分。也是Unity用来保证WebGL游戏运行效率的关键。他的主要作用就是对Javascript进行优化!提高JavaScript在浏览器中的运行效率。后面我们就具体的讲讲asm.js是如何做的。ASM.JS这次我们先直接看代码比较:先来个简单的C代码:int f(int i){\n
return i+1;\n} \n相应的asm.js代码:function f(i){\n
return (i+1)|0;\n}\n可以看到我们在每句后面都”比特或”上了0,这个操作对原来的变量里的值没有任何影响,看上去是无用的操作。但是它却保证了我们代码里的i和(i+1)都是整数而不是其他类型。另外一段:计算字符串长度size_t strlen(char *ptr){\n
char*curr =\n
while(*curr !=0){\n
return(curr-ptr);\n}\n相应的asm.js:function strlen(ptr){//calculate length of C string\n
ptr=ptr|0;\n
var curr=0;\n
while(MEM8[curr]|0!=0){\n
curr=(curr +1)|0;\n
return(curr-ptr)|0;\n} \n在代码中,MEM8是一个Byte类型的“View”,用来操作实际的”typed buffer”。(在这个例子中是ptr指向的内容。有关View和typed buffer的概念请参考 )类似的处理出现在asm.js的各个地方:asm.js中包含了JavaScript的一个严格子集 —— 包括严格类型的整数、浮点数、数值计算、函数调用和堆访问,使得其在被执行的时候跳过了导致JavaScript变缓慢的动态转换和其他一些操作,大大加快了速度。我们可以在代码中加入“use asm”开关开尝试开启asm.js模式。 function MyAsmModule(){\n
\"use asm\"\n
//module body\n}\nasm.js有一套自己的规范(具体可以参考),你完全可以自己手写asm.js代码,但更多的情况是利用上面提到的Emscripten自动的生成代码。如果浏览器支持asm.js,那么程序的代码会得到加速,但是如果浏览器不支持asm.js,也无需担心。asm.js本质上是JavaScript的一个子集,它用到的所有语法和JavaScript完全一致。在不支持asm.js的浏览器上执行的效率和一般的JavaScript脚本是一样的。目前支持asm.js的浏览器只有FireFox一家。IE和Chrome也在积极跟进。,在Windows 10中所使用的Chakra引擎将支持asm.js,并且微软正与Mozilla进行合作,以争取尽快实现它。Chrome则将通过TurboFan这一在V8上经过优化的编译器提供对asm.js的支持。如果你的Chrome版本是41,这意味着其已经内嵌的TruboFan Beta版,可以加速asm.js了。Unity例子测试首先你得有Unity5.0,使用官方或者自己的项目,切换到WebGL平台。我这里用的是官方的,将编译好的整个包放入到Web Server的目录中,然后在浏览器访问。在浏览器中打开项目的Html页面,找到并打开WebGL_Build.js,发现其中除了少量可以阅读的函数以外,文件的绝大部分内容都是类似用汇编形式写出的asm.js代码。我们游戏的绝大部分逻辑代码就出现在此总结Unity5.0中的WebGL平台部署是一个令人激动的选项,纯html的方式运行游戏意味着我们可以把更加复杂和有趣的游戏直接部署在网页上。让其在诸如微信这样的平台上直接传播。这个魔术的背后离不开IL2CPP,Emscripten和asm.js。asm.js有着化腐朽为神奇的力量,通过一套工作流转换,使我们获得高效的代码。高效的代码只是其中的一个好处,另外一个好处是代码混淆:由于asm.js的天性使然,这些看上去像极了汇编的代码很好的解决了html5游戏客户端源码直接暴露的风险。这一点对于商业游戏来说也非常重要。可以说asm.js天生就是为了WebGL游戏准备的!而从各大浏览器厂商对其支持力度也能看出以后的流行非它莫属。其实Emscripten+asm.js不光光是Unity可以使用,其他引擎也一样可以使用。例如Unreal3也使用同样的方法来将游戏带到浏览器上。而cocos2d-x也有。WebGL的前景一片光明。欢迎关注IndieACE微信公众号:IndieAce,可以看到IndieACE定期分享的好内容。需要转载IndieACE的文章请与我们私信联系。","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T14:06:13+08:00","url":"/p/","title":"Unity3D将来时:WebGL","summary":"作者: 随着Unity5.0的发布,WebGL平台的部署也正式登场(目前还处于Beta状态)。WebGL是一项利用JavaScript API呈现3D电脑图形的技术。区别于其他需要浏览器加载插件的形式(比如Flash和Unity的Web Player),通过使用WebGL技术,我们只需要编写…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":6,"likesCount":25}},"annotationDetail":null,"commentsCount":3,"likesCount":16,"FULLINFO":true}},"User":{"yizhimao":{"isFollowed":false,"name":"小玉","headline":"本体其实是一只猫(头像即本人)。","avatarUrl":"/a9d6a00d321a770c114e3f_s.jpg","isFollowing":false,"type":"people","slug":"yizhimao","bio":"独立游戏开发者","hash":"eb4132dbcc9ef3a0e9cfcdb","uid":96,"isOrg":false,"description":"本体其实是一只猫(头像即本人)。","profileUrl":"/people/yizhimao","avatar":{"id":"a9d6a00d321a770c114e3f","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"badge":{"identity":null,"bestAnswerer":null}}},"Comment":{},"favlists":{}},"me":{},"global":{"experimentFeatures":{"ge3":"ge3_9","ge2":"ge2_1","nwebStickySidebar":"sticky","newMore":"new","liveReviewBuyBar":"live_review_buy_bar_2","liveStore":"ls_a2_b2_c1_f2","isOffice":"false","homeUi2":"default","answerRelatedReadings":"qa_recommend_with_ads_and_article","remixOneKeyPlayButton":"headerButton","qrcodeLogin":"qrcode","newBuyBar":"livenewbuy3","newMobileColumnAppheader":"new_header","zcmLighting":"zcm","favAct":"default","appStoreRateDialog":"close","mobileQaPageProxyHeifetz":"m_qa_page_nweb","iOSNewestVersion":"4.2.0","default":"None","wechatShareModal":"wechat_share_modal_show","qaStickySidebar":"sticky_sidebar","androidProfilePanel":"panel_b"}},"columns":{"next":{},"indieace":{"following":false,"canManage":false,"href":"/api/columns/indieace","name":"IndieACE","creator":{"slug":"yizhimao"},"url":"/indieace","slug":"indieace","avatar":{"id":"8a94f50b9ef","template":"/{id}_{size}.jpg"}}},"columnPosts":{},"columnSettings":{"colomnAuthor":[],"uploadAvatarDetails":"","contributeRequests":[],"contributeRequestsTotalCount":0,"inviteAuthor":""},"postComments":{},"postReviewComments":{"comments":[],"newComments":[],"hasMore":true},"favlistsByUser":{},"favlistRelations":{},"promotions":{},"switches":{"couldAddVideo":false},"draft":{"titleImage":"","titleImageSize":{},"isTitleImageFullScreen":false,"canTitleImageFullScreen":false,"title":"","titleImageUploading":false,"error":"","content":"","draftLoading":false,"globalLoading":false,"pendingVideo":{"resource":null,"error":null}},"drafts":{"draftsList":[],"next":{}},"config":{"userNotBindPhoneTipString":{}},"recommendPosts":{"articleRecommendations":[],"columnRecommendations":[]},"env":{"edition":{},"isAppView":false,"appViewConfig":{"content_padding_top":128,"content_padding_bottom":56,"content_padding_left":16,"content_padding_right":16,"title_font_size":22,"body_font_size":16,"is_dark_theme":false,"can_auto_load_image":true,"app_info":"OS=iOS"},"isApp":false},"sys":{},"message":{"newCount":0},"pushNotification":{"newCount":0}}}

我要回帖

更多关于 我要自学网unity3d 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信