Unity3D手游开发执行

0x00 前言

趁微软愈开放,C#呢换得更加吸引众人的眼珠。而以打闹行业被,C#为起慢慢地赢得了关爱。这不,
网易绝代双娇手游团队已经到家使用.Net
Core支持前后端统一C#出,跨平台部署了。
图片 1

就此,我们就算来总结一下C#以玩行业被一些现实的运用吧。

《腾讯桌球:客户端总》

0x01 游戏引擎

商讨游戏领域的以,自然应事先来说说打引擎:

本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目我。虽然基于Unity3D,很多物一样适用于Cocos。本文由以下10生点开展阐述:

Unity

(Unity – Game
Engine)

图片 2

毋庸多说了咔嚓,随着“移动也帝”潮流的过来,Unity3D也转移得越来越流行。使用C/C++开发,提供C#用作脚本。
移动游戏开发必备神器,而且趁机VR热潮的赶到,使用U3D开发VR内容也格外利。总之,你值得拥有。

  1. 架构设计

  2. 原生插件/平台相互

  3. 本及补丁

  4. 为此剧本,还是不要?这是一个题目

  5. 资源管理

  6. 特性优化

  7. 异常与Crash

  8. 适配与配合

  9. 调节以及开发工具

  10. 路运营

Axiom

(Axiom)

图片 3

Axiom是一致迟迟开源且超过平台的3D渲染引擎,提供了针对性Windows, Linux, Android,
iPhone以及Windows Phone等各个平台的支撑。
刺探游戏开发之伴等一定听说过OGRE渲染引擎吧?
Axiom使用C#移植了OGRE。

图片 4图片 5图片 6

Torque X

(Torque X |
Products)

图片 7

由于GarageGames开发的相同慢基于XNA的2D/3D游戏引擎(但是不支持XNA Game Studio
4.0)。
使用C#出,目标平台要是PC以及XBox。
可是多效能都尚未开发了,目前曾经为废弃。

 

truevision3d

(3D Engine and Game Development SDK by
Truevision3D)

图片 8

根以C/C++开发,不过提供针对性VB6, VB.Net, C#,
Delphi,APL和BlitzMax的支持。
信任各位能够快上手。

1.架构设计

Xenko

(Home | Xenko)

图片 9

起源日本之开发商SiliconStudio,开发商老大靠谱。且和Unity3D相比,Xenko支持新型的本子的C#6和.Net4.6。且由依赖了Xamarin,因此当跨平台策略上不比较Unity3D差。
而,它还是免费开源的,不过由于用了GPL3协议,因此一旦是温馨去窜引擎代码就务须公开。
个人觉得十分风趣且值得研究的一个游戏引擎。

图片 10

MonoGame

(MonoGame)

图片 11

MonoGame是开源项目Mono的一个子,是Microsoft XNA 4.X
Framework开源实现。该框架的目标是若XNA可以重爱地出过平台游戏,并且可拓展代码的飞速复用。
作Mono的一个支,MonoGame的跨平台能力自然无需担心,它目前支撑iOS,
Android, MacOS, Linux, Windows,OUYA, PS4, PSVita以及Xbox One等平台。

哼的架使周边项目之几近人口组织开发同代码管理,也利用寻错误和末代维护。

0x02 图像相关

  • 框架的选料:需要根据集团、项目来开展选,没有最好好之框架,只有最适度的框架。

  • 框架的以:统一之框架能正式大家的表现,互相之间可比较平切换,可维护性大大提升。除此之外,还会代码解耦。例如StrangeIOC是一个超轻量级和高度可扩大的主宰反转(IoC)框架,专门为C#跟Unity编写。已清楚公司里使用StrangeIOC框架的打有:腾讯桌球、欢乐麻将、植物大战僵尸Online。<https://github.com/strangeioc/strangeioc>

XNA

图片 12

无须多说了咔嚓。微软自身的事物。XNA中之X表示能够当WindowsXbox和协作伙伴之间达成超过平台的精的软件工具。N表示“下一代(Next-
generation)”,A表示“架构(Architecture)”。基于DirectX的打支付环境。使用c#针对directx进行了包装。可以
在xbox360暨pc间实现跨平台。

 

OpenTK

(The Open Toolkit
Library)

封装了OpenGL, OpenCL以及OpenAL的C#库。

凭借注入(Dependency Injection,简称DI),是一个根本之面向对象编程的原理来减少计算机程序的耦合问题。依赖注入还有一个名字称为控制反转(Inversion of Control,英文缩写为IoC)。依赖注入是如此一个历程:由于某客户类只因让服务类的一个接口,而休靠让现实服务类,所以客户类就定义一个注入点。在程序运行过程被,客户类不直接实例化具体服务类实例,而是客户类的运转上下文环境专程组件肩负实例化服务类,然后拿其注入及客户类中,保证客户类的正常运转。即对象在为创造的上,由一个运作上下文环境要专门组件将该所依靠的服务类对象的援传递给她。也可说,依赖让注入到对象吃。故此,控制反转是,关于一个对象如何获取他所据的靶子的援,这个责任的反转

SDL.Net

(SDL.Net)

图片 13

SDL(Simple DirectMedia
Layer)可以管理视频,音频,输入设备,CD-ROM,线程,共享对象装载,联网和定时器。对于3D图形,它可拍卖OpenGL或Direct3D。开发库中以C语言编写,而SDL.Net是SDL库的C#版本。

 

SlimDX

(SlimDX
Homepage)

图片 14

SlimDX是一个免费开源之框架,基于DirectX,开发者可以下 C#, VB.NET,
或者IronPython进行开。

图片 15

0x03 物理相关

 

Box2Dx

(Box2Dx)

自己信任Box2D各位应该格外了解,Box2D自身是一个用于模拟2D刚体物体的C++引擎。而且它们并了大气之物理力学和运动学的乘除,并将大体模拟过程封装到近似对象被,将对体的操作,以略温馨之接口提供被开发者。我们只需要调用引擎中相应的目标要函数,就可套现实生活中的增速、减速、抛物线运动、万起引力、碰撞反弹等等各种真的大体位移。

而Box2Dx是Box2D的C#版本。

StrangeIOC采用MVCS(数据模型 Model,展示视图 View,逻辑控制 Controller,服务Service)结构,通过信息/信号进行互和通信。整个MVCS框架跟flash的robotlegs基本一致,(忽略语言不一致)详细的参阅<http://www.cnblogs.com/skynet/archive/2012/03/21/2410042.html>。

Box2D.XNA

(Box2D.XNA –
Home)

图片 16

与方面的近乎,当然对Xbox 360开了特别之优化。

  • 数据模型 Model:主要承担数据的储存和着力数据处理

  • 显示视图 View:主要担负UI界面展示同卡通片表现的处理

  • 逻辑控制 Controller:主要负责作业逻辑处理,

  • 服务Service:主要承担独立的大网收发请求等之有职能。

  • 信息/信号:通过信息/信号去解耦Model、View、Controller、Service这四种植模块,他们中通过信息/信号进行相互。

  • 绑定器Binder:负责绑定消息处理、接口和实例对象、View与Mediator的呼应关系。

  • MVCS Context:可以了解也MVC各个模块存在的上下文,负责MVC绑定和实例的缔造工作。

Farseer

(Farseer Physics
Engine)

图片 17

同是一个2d大体引擎,支持C#。当然它们也因Box2D,因此与Box2D有那么些一律的功用。

图片 18

Jitter

(Jitter)

末段介绍一个3D之物理引擎。支持使用C#。

腾讯桌球客户端项目框架

0x04 结语

可见到,C#在微软支持开源之前就是既在打领域发生矣森下。希望今天当微软从头源之支撑之下,C#能够在游玩世界得到重新多之关注。

 

  • 代码目录的团队:诚如客户端用得比较多的MVC框架,怎么分目录?

    • 预先照工作职能分,再遵照 MVC 来划分。”蛋糕心语”就是使的这种方式。
    • 优先随 MVC 划分,再比如工作功能划分。”D9″、”宝宝斗场”、”魔法花园”、”腾讯桌球”、”欢乐麻将”使用的这种方式。

图片 19

 

据悉使用习惯,可以自动选择。个人推举”先照工作职能分,再依
MVC 来划分”,使得模块更聚焦(高内聚),第二种艺术因此几近矣意识就项目的运营模块增多,没有第一栽那么好维护。

  • Unity项目目录的团伙:结合Unity规定之局部特种的用的文书夹,我们建议Unity项目文件夹组织办法如下。

图片 20

里,Plugins支持Plugins/{Platform}这样的命名规范:

  • Plugins/x86
  • Plugins/x86_64

  • Plugins/Android

  • Plugins/iOS

假若存在Plugins/{Platform},则加载Plugins/{Platform}目录下之文书,否则加载Plugins目录下的,也就是说,如果是{Platform}目录,Plugins根目录下的DLL是勿见面加载的。

除此以外,资源集团使用分文件夹存储”成品资源”及”原料资源”的主意处理:防止无关资源参与打包,RawResource即原始资源,Resource即成品资源。当然并无限于RawResource这种样式,其他Unity规定的特种文件夹都得以这么,例如Raw
Standard Assets。

 

  • 商厦组件
-   msdk(sns、支付midas、推送灯塔、监控Bugly)

-   apollo

-   apollo
    voice 
-   xlua

现阶段咱们的腾讯桌球、四皇家军棋都连了apollo,但是如果服务器无应用apollo框架,不建议客户端接apollo,而是一直接msdk减少二破封装信息之不见和带动的不当,方便以后升迁维护,并且减少导入无用的代码。

 

  • 老三正在插件选型
-   NGUI

-   DoTween

-   GIF

-   GAF

-   VectrosityScripts

-   PoolManager

-   Mad
    Level Manger 

 

2.原生插件/平台相互

图片 21

虽大多时下Unity3D进行打开发时,只需要使用C#展开逻辑编写。但奇迹不可避免的得采用及编排原生插件,例如有老三方插件才提供C/C++原生插件、复用已有的C/C++模块等。有部分功能是Unity3D实现不了,必须使调用Android/iOS原生接口,比如取手机的硬件信息(UnityEngine.SystemInfo没有供的组成部分)、调用系统的原生弹窗、手机激动等等

 

2.1C/C++插件

图片 22

编纂和运原生插件的几只根本点:

  • 创C/C++原生插件
-   导出接口必须是C ABI-compatible函数
-   函数调用约定
  • 在C#中标识C/C++的函数并调用
-   标识
    DLL 中的函数。至少指定函数的名称和包含该函数的 DLL
    的名称。 
-   创建用于容纳
    DLL 函数的类。可以使用现有类,为每一非托管函数创建单独的类,或者创建包含一组相关的非托管函数的一个类。

-   在托管代码中创建原型。使用 **DllImportAttribute** 标识 DLL
    和函数。 用 **static** 和 **extern** 修饰符标记方法。

-   调用
    DLL 函数。像处理其他任何托管方法一样调用托管类上的方法。
  • 在C#丁创造回调函数,C/C++调用C#反过来调函数
-   创建托管回调函数。

-   创建一个委托,并将其作为参数传递给 C/C++函数。**平台调用会自动将委托转换为常见的回调格式。**

-   确保在回调函数完成其工作之前,垃圾回收器不会回收委托。

 

那么C#同原生插件之间是什么兑现相互之间调用的吧?在干明白这个问题之前,我们先押下C#代码(.NET上之主次)的实施之过程:(更详细一点的介绍好参见我前写的博客:http://www.cnblogs.com/skynet/archive/2010/05/17/1737028.html)

  1. 拿源码编译为托管模块;

  2. 以托管模块组合为次集;

  3. 加载公共语言运行时CLR;

  4. 履行顺序集代码。

注:CLR(公共语言运行时,Common Language
Runtime)
跟Java虚拟机一样为是一个周转时环境,它担负资源管理(内存分配与废品收集),并确保应用及底操作系统之间必要之分开。

为提高平台的可靠性,以及为达成面向事务之电子商务应用所要求的风平浪静级别,CLR还要负责其他有任务,比如监视程序的运作。按照.NET的说法,在CLR监视之下运行的顺序属于“托管”(managed)代码,而无在CLR之下、直接以裸机上运行的采取或零部件属于“非托管”(unmanaged)的代码

立马几乎单经过本身总也产图:

图片 23

贪图
.NET上的程序运行

转调函数是托管代码C#遇之概念之函数,对回调函数的调用,实现自非托管C/C++代码中调用托管C#代码。那么C/C++是怎样调用C#的吧?大致分为2步,可以为此生图表示:

图片 24

  • 将回调函数指针注册到非托管C/C++代码中(C#遭到回调函数指委托delegate)

  • 调用注册过的托管C#函数指针

相较托管调用非托管,回调函数方式有点复杂一些。扭转调函数非常适合重复执行的天职、异步调用等景象下下

是因为地方的介绍好理解CLR提供了C#程序运行的条件,与非托管代码的C/C++交互调用也出于它来形成。CLR提供简单栽用于和非托管C/C++代码进行互的编制:

  • 阳台调用(Platform
    Invoke,简称PInvoke或者P/Invoke),它而托管代码能够调用从非托管DLL中导出的函数。

  • COM
    互操作,它如果托管代码能够透过接口及组件对象模型 (COM)
    对象交互。考虑超过平台性,Unity3D不采取这种方式。

 平台调用依赖让正数据在运转时寻找导出的函数并封送(Marshal)其参数。 下图显示了就等同进程。

图片 25

只顾:1.除事关回调函数时以外,平台调用方法调用从托管代码流向非托管代码,而不用会为相反方向流动。 虽然平台调用的调用只能从托管代码流向非托管代码,但是多少还是可以当输入参数或输出参数在个别单样子流动。2.图中DLL表示动态库,Windows平台指.dll文件、Linux/Android指.so文件、Mac
OS
X指.dylib/framework文件、iOS中不得不使用.a。后文都使用DLL代指,并且DLL使用C/C++编写

当”平台调用”调用非托管函数时,它以相继执行以下操作:

  • 搜寻包含该函数的DLL。

  • 用拖欠DLL加载到内存中。

  • 觅函数在内存中的地方并以那参数推到堆栈上,以封闭送所待的数据(参数)。

注意

只在第一次调用函数时,才会查找和加载 DLL 并查找函数在内存中的地址。iOS中使用的是.a已经静态打包到最终执行文件中。

  • 将控制权转移给非托管函数。

 

 2.2Android插件

图片 26

Java同提供了如此一个恢宏机制JNI(Java
Native Interface),能够及C/C++互相通信。

注:

  • JNI wiki-https://en.wikipedia.org/wiki/Java\_Native\_Interface,这里不透介绍JNI,有趣味的可活动去研究。如果您还不明白JNI也不用怕,就比如Unity3D使用C/C++库一样,用起来还是比较简单的,只待掌握者东西即可。并且Unity3D对C/C++桥接器这块做了包装,提供AndroidJNI/AndroidJNIHelper/AndroidJavaObject/AndroidJavaClass/AndroidJavaProxy方便使用等,具体应用后在介绍。JNI提供了若干的API实现了Java和另外语言的通信(主要是C&C++)。从Java1.1起来,JNI标准成为java平台的一律片,它同意Java代码和任何语言描绘的代码进行互动,保证本地代码能工作在其他Java 虚拟机环境下。”

  • 作文化扩展,提一下Android
    Java虚拟机。Android的Java虚拟机有2单,最开头是Dalvik,后面Google在Android
    4.4系新增同栽使运行模式ART。ART与Dalvik
    之间的严重性区别是那享超前 (AOT) 编译模式。 根据 AOT
    概念,设备安装使用时,DEX 字节代码转换仅进行相同差。 相比于
    Dalvik,这样可实现真正的优势 ,因为 Dalvik 的尽管时 (JIT)
    编译方法要在每次运行应用时还进展代码转换
    。下文中之所以Java虚拟机代指Dalvik/ART。

 

C#/Java都得与C/C++通信,那么通过编制一个C/C++模块作为桥接,就叫C#暨Java通信成为了也许,如下图所示:

图片 27

横流:C/C++桥接器本身和Unity3D没有直接涉及,不属于Android以及Unity3D,图备受位居Unity3D中凡是以代指libunity.so中实现的桥接器以象征真实的情事。

由此JNI既可以用来Java代码调用C/C++代码,也不过用来C/C++代码与Java(Dalvik/ART虚拟机)的交互。JNI定义了2个第一概念/结构:JavaVMJNIENVJavaVM供虚拟机创建、销毁等操作,Java中一个经过可以创建多个虚拟机,但是Android一个过程只能发出一个虚拟机JNIENV大凡线程相关的,对应之是JavaVM中之当前线程的JNI环境,只有附加(attach)到JavaVM的线程才生JNIENV指针,通过JNIEVN指针可以落JNI功能,否则不可知调用JNI函数。

图片 28

C/C++要访问的Java代码,必须使会顾到Java虚拟机,获取虚拟机有2被艺术:

  • 当加载动态链接库的下,JVM会调用JNI_OnLoad(JavaVM*
    jvm, void* reserved)
    ,第一只参数会传来JavaVM指针。
  • 在C/C++中调用JNI_CreateJavaVM(&jvm,
    (void**)&env, &vm_args)创建JavaVM指针

所以,我们唯有待以编排C/C++桥接器so的时节定义**JNI_OnLoad(JavaVM* jvm, void*
reserved)方法即可,然后把JavaVM指针保存起来作为上下文使用**。

取得到JavaVM之后,还非克一直用到JNI函数去抱Java代码,必须经线程关联的JNIENV指针去得到。所以,作为一个好的支付习惯于每次得到一个线程的JNI相关功能时,先调用AttachCurrentThread();又或者历次经过JavaVM指针获取当前底JNIENV:java_vm->GetEnv((void**)&jni_env, version),一定是曾附加到JavaVM的线程。通过JNIENV可以抱到Java的代码,例如你想当地面代码中做客一个靶的字段(field),你可以像下这样做:

  1. 对于类,使用jni_env->FindClass获取接近对象的援

  2. 于字段,使用jni_env->GetFieldId得字段ID

  3. 采用相应之计(例如jni_env->GetIntField)获取字段的价值

接近地,要调用一个方法,你step1.得得一个好像对象的援obj,step2.是方式methodID。这些ID通常是依赖为运行时中数据结构。查找到它们要数字符串比较,但万一你其实去实施其赢得字段或者开方法调用是很急匆匆的。step3.调用jni_env->CallVoidMethodV(obj, methodID, args)

从上面的以身作则代码,我们好观看使用原的JNI方式去与Android(Java)插件交互是多之麻烦,要和谐开最多的事情,并且以性需要好着想缓存查询到的点子ID,字段ID等等。幸运的是,Unity3D已经为我们封装好了这些,并且考虑了性优化。Unity3D主要提供了转2独级别之卷入来支援高效编写代码:

图片 29

流动:Unity3D中对应之C/C++桥接器包含在libunity.so中。

  • Level
    1:AndroidJNI、AndroidJNIHelper,原始之卷入相当给我们地方自己编辑的C#
    Wrapper。AndroidJNIHelper 和AndroidJNI自动完成了过多职责(指找到类定义,构造方法等),并且采用缓存使调用java速度更快。AndroidJavaObject和AndroidJavaClass基于AndroidJNIHelper 和AndroidJNI创建,但于拍卖自动完成部分吗发出广大和谐之逻辑,这些看似为生静态的本,用来走访java类的静态成员。更详尽接口参考帮助文档:http://docs.unity3d.com/ScriptReference/AndroidJNI.html,http://docs.unity3d.com/ScriptReference/AndroidJNIHelper.html

  • Level
    2:AndroidJavaObject、AndroidJavaClass、AndroidJavaProxy,这个3个像样是因Level1的包提供了双重强层级的包裹使用起来又简便,这个当第三有的缕介绍。

 

2.3iOS插件

图片 30

iOS编写插件比Android要简单很多,因Objective-C也是
C-compatible的,完全匹配标准C语言。
这些就得非常简单的保一重合 extern
“c”{},用C语言封装调用iOS功能,暴露被Unity3D调用。并且可跟原生C/C++库一样编成.a插件。C#同iOS(Objective-C)通信的规律跟C/C++完全等同:

图片 31

 

 

除开,Unity
iOS支持插件自动集成方式。所有在Asset/Plugings/iOS文件夹着后缀名为.m ,
.mm , .c ,
.cpp的文书都用自动并入到就变更的Xcode项目受到。然而,最终编进执行文书中。后缀为.h的文件不可知给含有在Xcode的花色树中,但他俩拿出现在目标文件系统中,从而使.m/.mm/.c/.cpp文件编译。这样编写iOS插件,除了需要针对iOS
Objective-C有必然了解外面,与C/C++插件没有异样,反而再也简短。

 

3.版和补丁

图片 32

其它游戏(端游、手游)都应有提供娱乐内更新的路。一般娱乐分为全量更新/整包更新、增量更新、资源创新。

  • 全量

android游戏内总体安装包下载(ios跳反到AppStore下载)

 

  • 增量:主要指android省流量更新
-   可以使用bsdiff生成patch包

-   应用宝也提供增量更新sdk可供接入

 

  • 资源

Unity3D通过行使AssetBundle即可实现动态更新资源的效能。

 

手游在落实这块时用专注的几点:

  1. 游戏发布有一定要供戏内更新的不二法门。即使是删掉测试,保不准这中间需进行资源或BUG修复更新。很多玩家并不知道如何翻新,而且Android手机应用分发平台多样,分发平台自吗不见面和官方并创新(特别是小之散发平台)。

  2. 更新功能而提供强制更新、非强制更新配置化选项,并指定哪些版本可以不愈更,哪些版本必须强还。

  3. 当打提供非强制更新功能下,现网一定会有多单本子。如果用对不同版本做不同的创新,例如配置文件A针对1.0.0.1窜了平等起,针对1.0.0.2修改了另外一样宗,2只版本需要各自更新对应的改动,需要自己实现创新策略IIPS不提供这效果。当用复杂的创新策略,推荐自己修更新服务器和客户端逻辑,不行使iips组件(其实自己实现呢生粗略)。

![](https://images2015.cnblogs.com/blog/92071/201604/92071-20160419000347366-1630977637.png)

没有运营经验的人会选择二进制,认为二进制安全、更小,这对端游/手游外网只存在一个版本的游戏适合,对一般不强升版本的手游并不适合,反而会对更新和维护带来很大的麻烦。
  1. 安排使用XML或者JSON等文本格式,更便利多本的配合和创新。最初步腾讯桌球客户端采用的老二向前制格式(由excel转换而来),但是就运营配置格式需要多字段,这样一直版本程序即使解析不了初的二进制数据,给兼容和更新带来了十分老之辛苦。这样就算要求地方提到的针对性无同步做不同更新,又或者配置一始发即留给好足够的扩大项,其实不管怎么预留扩展为生不便及达到求的变化,而且同开始见面把配置表复杂化但是实际只是发同样布置或几摆设才会转移结构。
 
  1. iOS版本的送审版本要连接一定的带有新情节之服务器,现网服务器还免包含新内容。送审通过后,上架游戏现网服务器会进展创新,iOS版本需要连接现网服务器如果未送真的服务器,但是就中还要休可知改改客户度,这个切换需通过服务器发开关进行支配。例如通过点名送审的iOS游戏版本号,客户端判断当地版本号是否为送审版本,如果是连接送审服务器,否则连现网服务器。

 

4.用本子,还是不要?这是一个题目

图片 33

便宜更新,减少Crash(特别是用C++的cocos引擎)

经过上面一样节约【版本和补丁】知道如果落实代码更新是坏紧的,正式这个由客户端支付的下压力是比特别之,如果起了比较严重的BUG必须作强制更新版本,使用脚本可以解决是题材。

由Unity3D手游更新资金较异常,而且目前腾讯桌球要求不能够强制更新,这招新本子的位移覆盖率提升于缓慢、出现问题以后难以修复。针对这状态,考虑引入lua进行运动开,后续发布移动与修复bug只待发布lua资源,进行资源创新即可,大大降低了发布和修补问题的本钱。

可选方案还有使用Html5开展活动出,目前游乐中早已先行埋了Html5移动入口,并且一度为此来发了”玩家调查”、”腾讯棋牌宣传”等。但是与lua对比,不能够就和Unity3D的吃水融合,体验不如使用lua,例如非可知操作游戏中之ui、不能够一气呵成复杂界面的制作、不克复用已有的职能、玩家付费充值和已部分吧会发出距离

 

玩脚论之君——Lua

当铺子里魔方比较好用lua,火隐忍者(手游)unity+ulua,全民水浒cocos2d-x+lua等等都产生使用lua进行支付。我们得以行使企业间的xlua组件,也可以动用ulua<http://ulua.org/>、UniLua<https://github.com/xebecnan/UniLua>等等。

 

5.资源管理

图片 34

 

5.1资源管理器

图片 35

 


业务并非一直用引擎或系统原生接口,而是包一个资源管理器负责:资源加载、卸载


兼容Resource.Load与AssetBundle资源彼此变更需要,开发中利用Resource.Load方式若毋庸打AB包效率还胜似


加载资源时,不管是一头加载还是异步加载,最好是用异步编码方式(回调函数或者信息通知机制)。如果哪一样龙资源由本土加载改呢打服务器按需要加载,而玩耍受之逻辑都是共方式编码的,改起来以异常痛苦。其实异步编码方式很简单,不比较并方式复杂。

 

5.2资源类型

图片 36

 

  • 图/纹理(对性能、包体影响极其深要素)

  • 音频

-   背景音乐,腾讯桌球使用.ogg/.mp3

-   音效,腾讯桌球使用.wav
  • 数据
-   文本

-   二进制
  • 动画/特效

 

5.3图片-文件格式与纹理格式

图片 37

常用之图像文件格式来BMP,TGA,JPG,GIF,PNG等;
常用之纹路格式来R5G6B5,A4R4G4B4,A1R5G5B5,R8G8B8, A8R8G8B8相当。

 

文件格式是图像为存储信息如果使的针对信息的例外编码方式,它存储于磁盘中,或者内存中,但是连无可知于GPU所识别,因为坐向量计见长的GPU对于这些纷繁的计无能为力。这些文件格式当让玩读入后,还是用通过CPU解压成R5G6B5,A4R4G4B4,A1R5G5B5,R8G8B8,
A8R8G8B8当像素格式,再传递至GPU端进行下。

纹理格式是力所能及吃GPU所识别的例如素格式,能于很快寻址并采样。举个例子,DDS文件是玩玩支付被常用之文件格式,它里面可以蕴涵A4R4G4B4的纹路格式,也堪涵盖A8R8G8B8底纹理格式,甚至好蕴涵DXT1的纹路格式。在这边DDS文件有点容器的代表。OpenGL
ES
2.0支持上述关联的R5G6B5,A4R4G4B4,A1R5G5B5,R8G8B8,A8R8G8B8等纹理格式,其中
R5G6B5,A4R4G4B4,A1R5G5B5每个像素占用2个字节(BYTE),R8G8B8每个像素占用3单字节,A8R8G8B8每个像素占用
4只字节。

 

基于OpenGL
ES的回落纹理有普遍的如下几种实现:

1)ETC1(Ericsson
texture compression),ETC1格式是OpenGL
ES图形标准的平等有,并且为有的Android设备所支撑。

2)PVRTC
(PowerVR texture compression),支持的GPU为Imagination
Technologies的PowerVR SGX系列。
3)ATITC (ATI texture compression),支持的GPU为Qualcomm的Adreno系列。
4)S3TC (S3 texture
compression),也深受称为DXTC,在PC上广泛被使用,但是在运动装备及或属于非常事物。支持的GPU为NVIDIA
Tegra系列。

 

图片 38

 

5.4资源工具

图片 39

起了专业就是可做工具检查,从源头及包

  • 资源导入检查

  • 资源打包检查

 

6.性能优化

图片 40

掉帧主要对GPU和CPU做分析;内存占用大重点对美术资源,音效,配置表,缓存等分析;卡顿也用对GPU和CPU峰值分析,另外IO或者GC也便于造成。

图片 41

6.1工欲善其事,必先利其器

图片 42

 

  • Unity
    Profiler
  • XCode instruments

  • Qualcomm Adreno
    Profiler

  • NVIDIA
    PerfHUD ES Tegra

 

6.2CPU:最佳标准减少计算

图片 43

  • 复用,UIScrollView
    Item复用,避免频繁创建销毁对象
  • 缓存,例如Transform

  • 运算裁剪,例如碰撞检测裁剪

-   粗略碰撞检测(划分空间——二分/四叉树/八叉树/网格等,降低碰撞检测的数量)

-   精确碰撞检测(检查候选碰撞结果,进而确定对象是否真实发生碰撞)

-   休眠机制:避免模拟静止的球
  • 逻辑帧与渲染帧分离

  • 分帧处理

  • 异步/多线程处理

 

6.3GPU:最佳条件减少渲染

图片 44

  • 纹理压缩

  • 批处理减少DrawCall(unity-Static
    Batching和Dynamic Batching,cocos SpriteBatchNode)

  • 抽无效/不必要绘制:屏幕外之剪裁,Flash脏矩阵算法,

  • LOD/特效分档

  • NGUI动静分离(UIPanel.LateUpdate的吃)

  • 支配角色骨骼数、模型面数/顶点数

  • 降帧,并非有场景都待60轴(腾讯桌球游戏场景60幅,其他场景30帧;天天酷跑,在开玩前,FPS被限制也30,游戏开始之后FPS才为60。天天飞车的FPS为30,但是当用户一段时间不点击界面后,FPS自动降)

 

6.4内存:最佳标准减少内存分配/碎片、及时放出

图片 45

  • 纹理压缩-Android
    ETC1、iOS PVRTC 4bpp、windows DXT5
  • 对象池-PoolManager

  • 统一空闲图集

  • UI九宫格

  • 剔除不用的剧本(也会见占有内存)

 

6.5IO:最佳条件减少/异步io

图片 46

 

  • 资源异步/多线程加载

  • 预加载

  • 文本减少

  • 合理规划资源统一打包,并非texturepacker打包成稀图集一定好,会多文件io时间

 

6.6网:其实呢是IO的平种

图片 47

动单线程——共用UI线程,通过波/UI循环驱动;还是多线程——单独的大网线程?

  • 单线程:由游戏循环(事件)驱动,单线程模式于下多线程模式开发、维护简单好多,但是性能于多线程要不等有,所以当网络IO的早晚,需要专注别阻塞到打循环。说明,如果网络IO不复杂的动静下,推荐使用该模式。
-   在UI线程中,别调用可能阻塞的网络函数,优先考虑非阻塞IO

-   这是网络开发者经常犯的错误之一。比如:做一个简单如
    gethostbyname()
    的调用,这个操作在小范围中不会存在任何问题,但是在有些情况中现实世界的玩家却会因此阻塞数分钟之久!如果你在
    GUI 线程中调用这样一个函数,对于用户来说,在函数阻塞时,GUI
    一直都处于 frozen 或者 hanged
    状态,这从用户体验的角度是绝对不允许的。 
  • 大多线程:单独的大网线程,使用独立的大网线程有一个分外鲜明的益处,主线程可以用水污染活、累活交给网络线程做使UI更通畅,例如消息之编解码、加解密工作,这些还是好耗时的。但是采取多线程,给开发以及保护带来一定财力,并且要没有早晚之涉写出来的网库不那么安静,容易失误,甚至导致游戏崩溃。下面是几乎点注意事项:
-   千万千万别在网络线程中,回调主线程(UI线程)的回调函数。而是网络线程将数据准备好,让主线程主动去取,亦或者说网络线程将网络数据作为一个事件驱动主线程去取。当年我在用Cocos2d-x +
    Lua做魔法花园的手机demo时,就采用的多线程模式,最初在网络线程直接调用主线程回调函数,经常会导致莫名其妙的Crash。因为网络线程中没有渲染所必须的opengl上下文,会导致渲染出问题而Crash。

6.6包大小

图片 48

 

  • 采取压缩格式的纹理/音频

  •  尽量不要使用System.Xml而用于小之Mono.Xml

  •  启用Stripping来减多少仓库底大大小小

  •  Unity
    strip level(strip by byte code)

  •  Unity3D输出APK,取消X86架构

  •  iOS Xcode strip开启

 

6.7耗电

图片 49

下面影响耗电之几乎只元素以及熏陶过摘自号里面的一致首文章。

图片 50

 

 

7.异常与Crash

图片 51

7.1防御式编程

图片 52

 

  • 不法的输入被维护你的程序
-   检查每一输入参数

-   检查来自外部的数据/资源
  • 断言
  • 错误处理

  • 隔栏

 

防不胜防,不管如何守护总有失手的时光,这就算需非常捕获和反馈。

 

7.2非常捕获

图片 53

可怜捕获已经发许多老三零件可供应对接,这里不介绍组件的假设连贯抱,而是简单说一下十分捕获的法则。

图片 54

鉴于许多破绽百出并无是发在出工作者调试阶段,而是在用户还是测试工作者用阶段;这即需要相关代码维护工作者于程序非常捕获收集现场消息。异常及Crash的监察和报告,这里不介绍Bugly的应用,按照apollo或者msdk的文档接入即可,没有最好多足说之。这里要通过Bugly介绍手游的几乎类非常的捕获和剖析:

  • Unity3D
    C#臃肿异常捕获:比较简单使用Application.RegisterLogCallback/Application.RegisterLogCallbackThreaded(在一个新的线程中调用委托)注册回调函数。特别注意:保证项目蒙唯有出一个Application.RegisterLogCallback注册回调,否则后面注册的会晤蒙前注册之回调!转头调函数吃stackTrace参数包大调用栈。

public void HandleLog(string logString, string stackTrace, LogType type)

{

    if (logString == null || logString.StartsWith(cLogPrefix))

    {

        return;

    }

   

    ELogLevel level = ELogLevel.Verbose;

    switch (type)

    {

   

        case LogType.Exception:

            level = ELogLevel.Error;

            break;

        default:

            return;

    }

   

    if (stackTrace != null)

    {

        Print(level, ELogTag.UnityLog, logString + "\n" + stackTrace);

    }

    else

    {

        Print(level, ELogTag.UnityLog, logString);

    }

}

 

  • Android
    Java层异常捕获

try…catch显式的抓获异常一般是休招游戏Crash的,它同时称为编译时死,即于编译阶段为拍卖的酷。编译器会强制程序处理所有的Checked异常,因为Java认为就类似非常都是得吃处理(修复)的。如果没try…catch这个老,则编译出错,错误提示类似于”Unhandled exception type xxxxx”。
UnChecked异常而称为运行时好,由于尚未对号入座的try…catch处理该特别对象,所以Java运行条件将会见终止,程序用退出,也便是咱们所说之Crash。那怎么不见面加在try…catch呢?

  • 束手无策用富有的代码都长try…catch

  • UnChecked异常通常都是比较严重的可怜,或者说既坏了运行条件之。比如内存地址,即使我们try…catch住了,也不克明了知道哪处理该生,才能够担保程序连接下的周转是不易的。

Uncaught异常会招应用程序崩溃。那么当崩溃了,我们是不是可以做些什么吧,就比如Application.RegisterLogCallback注册回调打印日志、上报服务器、弹窗提示用户?Java提供了一个接口给咱们,可以做到这些,这就算是UncaughtExceptionHandler,该接口含有一个纯虚函数:

public abstract void uncaughtException (Thread thread, Throwableex)

Uncaught异常发生时会见停下线程,此时,系统即会通知UncaughtExceptionHandler,告诉它给停止的线程以及相应之特别,然后就会调用uncaughtException函数。如果该handler没有被显式设置,则会调用对应线程组的默认handler。如果我们而捕获该生,必须贯彻我们好之handler,并通过以下函数进行安装:

public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler handler)

特别注意:多次调用setDefaultUncaughtExceptionHandler设置handler,后面注册之会盖前注册之,以最后一浅为遵循。实现从定义的handler,只待继承UncaughtExceptionHandler该接口,并促成uncaughtException方法即可。

static class MyCrashHandler implements UncaughtExceptionHandler{  

    @Override  

    public void uncaughtException(Thread thread, final Throwable throwable) {  

        // Deal this exception

    }

}

于任何线程中,都可经setDefaultUncaughtExceptionHandler来设置handler,但当Android应用程序中,全局的Application和Activity、Service都与属于UI主线程,线程名称默认为”main”。所以,在Application中应为UI主线程添加UncaughtExceptionHandler,这样任何程序中之Activity、Service中起的UncaughtException事件还可以让拍卖。

捕获Exception之后,我们尚需明白崩溃堆栈的信,这样有助于我们解析崩溃的因由,查找代码的Bug。异常对象的printStackTrace方法用于打印好的库房信息,根据printStackTrace方法的输出结果,我们得找到非常的源流,并跟踪至死联机触及的长河。

public static String getStackTraceInfo(final Throwable throwable) {

    String trace = "";    try {

        Writer writer = new StringWriter();

        PrintWriter pw = new PrintWriter(writer);

        throwable.printStackTrace(pw);

        trace = writer.toString();

        pw.close();

    } catch (Exception e) {        return "";

    }    return trace;

}

  • Android
    Native
    Crash:前面我们理解得编制和运C/C++原生插件,除非C++使用try…catch捕获异常,否则一般会一直crash,通过捕获信号进行拍卖。
  • iOS
    异常捕获:

跟Android、Unity类似,iOS也提供NSSetUncaughtExceptionHandler 来举行充分处理。

#import "CatchCrash.h"

   

@implementation CatchCrash

   

void uncaughtExceptionHandler(NSException *exception)

{

    // 异常的堆栈信息

    NSArray *stackArray = [exception callStackSymbols];

    // 出现异常的原因

    NSString *reason = [exception reason];

    // 异常名称

    NSString *name = [exception name];

    NSString *exceptionInfo = [NSString stringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray];

    NSLog(@"%@", exceptionInfo);

       

    NSMutableArray *tmpArr = [NSMutableArray arrayWithArray:stackArray];

    [tmpArr insertObject:reason atIndex:0];

   

    [exceptionInfo writeToFile:[NSString stringWithFormat:@"%@/Documents/error.log",NSHomeDirectory()]  atomically:YES encoding:NSUTF8StringEncoding error:nil];

}

   

@end

但是内存访问错误、重复释放等错误引起崩溃就无法了,因为这种似是而非它抛来底凡信号,所以还得要特别召开信号处理。

  • windows
    crash:同样windows提供SetUnhandledExceptionFilter函数,设置最高一级的酷处理函数,当次出现任何不处理的怪,都见面硌发而设置的函数里,然后以挺处理函数中取得程序非常时之调用堆栈、内存信息、线程信息相当。

 

 

8.适配与配合

图片 55

 

8.1UI适配

图片 56

 

  • 锚点(UIAnchor、UIWidgetAnchor属性)

  • NGUI UIRoot统一安装缩放比例

  • UIStretch

 

8.2兼容

图片 57

 

  • shader兼容:例如if语句有的机型支持不好,Google
    nexus 6在shader中动用了if就见面crash
  • 书兼容:android复杂的条件,有的手机厂商和rom会针对字体进行优化,去掉android默认字体,如果非自包字体会不现实中亲笔

 

9.调剂以及开发工具

图片 58

9.1日记与跟踪

图片 59

事实证明,打印日志(printf调试法)是特别实惠的章程。一个吓用之日记调试,必备以下几单力量:

  • 日志面板/控制台,格式化输出

  • 洋洋洒洒级别(verbosity
    level):ERROR、WARN、INFO、DEBUG

  • 频道(channel):按职能等开展模块划分,如网频道特收取/显示网络模块的信息,频道建议用枚举进行命名。

  • 日志同时会输出及日志文件

  • 日记上报

 

9.2调剂用绘图工具

图片 60

调节绘图用工具指开发及调试中为可视化的绘图用工具,如腾讯桌球开发调试时见面用VectrosityScripts可视化球桌的物理模型(实际碰撞线)帮助调节。这类似工具得以省大量工夫跟便捷定位问题。通常调试用绘图工具包含:

  • 支撑绘制基本图形,如直线、球体、点、坐标轴、包围盒等

  • 支持从定义配置,如颜色、粒度(线之粗细/球体半径/点的深浅)等

 

9.3玩耍内置菜单/作弊工具

图片 61

于开发调试中提供戏展开中的局部布置选和作弊工具,以利于调试以及提高效率。例如腾讯桌球游戏被提供:

  • 游玩内物理引擎参数调整菜系;

  • 改球杆瞄准线长度/反射线数量、修改签到奖励领取天数等作弊工具

只顾游戏内之具备开支调试用的工具,都需要经过编译宏开关,保证发布版不见面管工具代码包含进去

 

9.4Unity扩展

图片 62

Untiy引擎提供了怪强大的编辑器扩展功能,基于Unity
Editor可以兑现深多的职能。公司内部、外部都出不行之开源扩展可用

商厦标,如GitHub上之:

UnityEditor-MiniExtension

Unity-Resource-Checker

UnityEditorHelper

MissingReferencesUnity

Unity3D-ExtendedEditor

商家中:

TUT、BeautyUnity、UnityDependencyBy

 

 

10.型运营

图片 63

 

  • 自行构建
-   版本号——主版本号.特性版本号.修正版本号.构建版本号


    -   \[构建版本号\]应用分发平台升级判断基准


-    自动构建


    -   Android

    -   iOS
        — XUPorter 

   

 公司之中接入SODA即可,建议搭建自己之构建机,开发期间每日N
Build排队会死人的,另外呢得搭建自己的搭建构建平台

 

  • 统计上报
-   Tlog上报


    -   玩家转化关键步骤统计(重要)

    -   Ping统计上报

    -   游戏业务的统计上报(例如桌球球局相关的统计上报)


-    灯塔自定义上报

 

  • 运营模板
-   配置化

-   服务器动态下发

-   CDN拉取图片并缓存

 

图片 64

上线前的checklist

项目

要点

说明

指标

灯塔上报

1. 灯塔自带统计信息
2. 自定义信息上报

灯塔里面包含很多统计数据,需要检查是否ok

1. 版本/渠道分布
2. 使用频率统计
3. 留存统计(1天留存、3天留存、7天留存、14天留存)
4. 用户结构统计(有效用户、沉默用户、流失用户、回流用户、升级用户、新增用户)
5. 硬件统计(机型+版本、分辨率、操作系统、内存、cpu、gpu)
6. Crash统计(Crash版本、Crash硬件、Crash次数等)
等等

信鸽推送

   

能够针对单个玩家,所有玩家推送消息

米大师支付

   

正常支付

安全组件

1. TSS组件接入
2. 隐藏内部符号表:C++开发的代码使用strip编绎选项,抹除程序的符号
3. 关键数据加密,如影子变量+异或加密算法

根据安全中心提供的文档完成所有项

接入安全组件,并通过安全中心的验收

稳定性

crash率

用户crash率:发生CRASH的用户数/使用用户数
启动crash率:启动5S内发生crash用户数/使用用户数

低于3%

弱网络

 

断线重连考虑,缓存消息,重发机制等等

客户端的核心场景必须有断线重连机制,并在有网络抖动、延时、丢包的网络场景下,客户端需达到以下要求:
一. 不能出现以下现象:
1、游戏中不能出现收支不等、客户端卡死/崩溃等异常情况;
2、游戏核心功能(如登录、单局、支付等)不能有导致游戏无法正常进行的UI、交互问题;
3、不能有损害玩家利益或可被玩家额外获利的问题;
4、需要有合理的重连机制,避免每次重连都返回到登录界面。
二. 需要对延时的情况有相应的提示

兼容性

   

通过适配测试

游戏更新

1. 整包更新
2. 增量更新

 

特别说明:iOS送审版本支持连特定环境,与正式环境区别开,需要通过服务器开关控制

性能

内存、CPU、帧率、流量、安装包大小

 

【内存占用要求】
Android平台:在对应档次客户端最低配置以上,均需满足以下内存消耗指标(PSS):
1档机型指标:最高PSS<=300MB (PSS高于这个标准会影响28%用户的体验,约1800万)
2档机型指标:最高PSS<=200MB(PSS高于这个标准会影响45%用户的体验,约3000万)
3档机型指标:最高PSS<=150MB(PSS高于这个标准会影响27%用户的体验,约1800万)
iOS平台:在对应档次客户端最低配置以上,均需满足以下内存消耗指标(PSS):
1档机型指标:消耗内存(real mem)不大于250MB(高于这个标准会影响53%用户的体验,约1900万)
2档机型指标:消耗内存(real mem)不大于200MB(高于这个标准会影响47%用户的体验,约1700万)
【CPU占用要求】
Android平台:CPU占用(90%)小于60%
iOS平台:CPU占用(90%)小于80%
【帧率要求】
1档机型(CPU为四核1.4GHZ,RAM为2G)或以上机型:游戏核心玩法中,最小FPS应不小于25帧/秒
2档机型(CPU为两核1.1GHZ,RAM为768M)或以上机型:游戏核心玩法中,最小FPS应不小于25帧/秒
3档机型(CPU为1GHZ,RAM为768M)或以上机型:游戏核心玩法中,最小FPS应不小于18帧/秒
【流量消耗要求】
游戏核心玩法流量消耗情况(非一次性消耗)应满足以下条件:
1.对于分局的游戏场景,单局消耗流量不超过200KB
2.对于不分局游戏场景或流量与局时有关的场景,10分钟消耗流量不超过500KB

 

 

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注