Unity3d开发入门指南
大家对Unity3D游戏引擎应该并不陌生,因为Unity3D在轻量级游戏开发和跨平台上面有他独特的优势,所以在当前可谓是炙手可热。下面简单介绍了Unity3D的一些基础。1 Unity3D简介
1.1 编辑器简介
编辑器整体视图如图1.1所示。里面包括了Unity常用的编辑窗口:
图1.1 Unity编辑器界面
Project视图、Hierarchy视图、Scene视图、Game视图、Inspector视图、Console视图、Profiler视图。
1.1.1 Project视图
Project视图可以理解为工程目录,里面罗列了工程里面的所有资源文件。常见的资源包括:脚本、预设(Prefab)、模型、贴图、动画、Shader等。用户可以通过右上角的搜索框,搜索工程内的文件。
1.1.2 Hierarchy视图
Hierarchy视图显示了当前游戏场景中,所有的游戏对象。游戏对象是通过树形结构排布,展开后可以看到每个子节点对象。常用的游戏对象包括:摄像机、场景物件、玩家、光源等。
1.1.3 Game视图
Game视图是游戏视角,即游戏最终展示给玩家的内容。游戏视角包括两部分:1、场景中当前摄像机照射的场景;2、游戏UI界面。
1.1.4 Scene视图
Scene视图有点像3DMax的编辑环境,在这里可以看到当前场景中的所有游戏对象。双击Hierarchy中的游戏对象,可以在Scene中定位到对应的物件。在游戏运行期间,暂停游戏。开发人员可以在Scene中找到对应的游戏对象,查看当前帧的世界场景,方便查找BUG。
1.1.5 Inspector视图
Inspector视图是游戏对象的属性面板。选择一个物件后,可以在Inspector面板中查看或编辑游戏对象的属性。游戏运行期间,修改游戏对象属性,可以马上作用到游戏对象。这一特点对于美术的编辑、程序查BUG或者策划调整游戏参数有很大帮助。
Unity的游戏对象是通过Component(组件)控制的。常见的Component有:Transform(模型坐标)、Collider(碰撞检测器)、Rigidbody(刚体属性)、Animation(动画)、AudioSource(声音源)、Script(游戏脚本)等。
1.1.6 Console视图
Console视图是控制台信息输出窗口。输出的信息包括:游戏脚本编译错误信息、游戏运行期间的日志输出、断言、崩溃信息。
1.1.7 Profiler视图
Profiler视图是游戏性能分析器。游戏运行期间,每一帧的数据都被记录,并显示在Profiler窗口。在时间轴上,最多可以保存几百帧的数据,点击一个特定的帧上,窗口下面会显示该帧的游戏运行细节,包括CPU使用率、GPU使用率、渲染、内存、音频、物理。
1.2 打包与发布
在Unity编辑器中,选择“File -> Build Settings”可以打开游戏打包发布面板。在此面板中,可以选择打包的游戏场景、发布平台以及游戏设置。Unity支持跨平台,所以在这里可以有多种平台选择。打包后的文件格式有:*.swf、*.exe、*.apk、Xcode工程等。
1.3 脚本组件
Unity游戏开发中,游戏脚本在游戏开发中是关键要素,游戏的逻辑控制都是由脚本来控制的。Unity支持3种游戏脚本语言:C#、JavaScript和Boo。这三种语言中,C#因为最接近C++更符合大部分程序员编程习惯,所以使用的比较广。而JavaScript就比较容易上手属于入门级别,Boo的使用人数则是最少的。
游戏脚本(类)继承自MonoBehaviour后,该脚本即可以作为一个游戏组件挂到游戏对象上。继承MonoBehaviour后,提供大部分系统控制的脚本函数。下面列了一些常用的函数的执行顺序:
不同游戏脚本之间的执行顺序,可以通过调整游戏脚本优先级来修改。(打开调整面板方式:选择某个脚本文件,在Inspector面板,点击右上角的Execution Order按钮。)
1.4 场景切换与数据传递
在打包发布面板,我们可以选择需要包含的游戏场景。在游戏过程中,我们需要切换场景,可以调用Application.LoadLevel()函数。
切换场景的时候,默认会把场景中的物件清空。如果需要把数据从不同场景中传递成问题了。常用的方法有两种:
1、 静态数据变量。静态数据变量可以用来桥接不同脚本之间的数据交换。当然也可以作为不同场景之间的数据传递。当然过多的静态变量,对于其管理也是个比较麻烦的问题。
2、 利用函数DontDestroynoxss()指定某些物件不随着场景的切换而移除。定义一个长期存在的节点,其实挺方便的。可以把游戏的主框架搭建放在这个节点的脚本控件上,这个脚本就有点像GameMain函数,里面可以定义单件管理器,方便管理游戏数据和流程。
1.5 GUI
Unity提供一套自带的GUI系统,但是这套GUI系统实在是太难用了。几乎没有游戏会使用这个原生GUI系统的,也因此催生了很多UI插件。市面上成功用Unity开发的游戏,都是使用UI插件的。最常见的UI插件有:NGUI 和EZGUI。天天飞车采用的是NGUI,所以本文简单介绍一下NGUI。
1.5.1 原生GUI系统
原生GUI系统的运行效率低,而且UI需要由程序调整控制,生产效率极低。
下面,我们看一个Unity官网提供的一个用GUI系统的例子。如图1.2,我们需要绘制两个按钮,点击按钮对应输出一个提示语句。代码1是官方给出的代码程序。
可见如果需要调整按钮位置,修改按钮的外观,可能需要修改程序脚本。如果UI较少尚且可以这样做。但是如果游戏UI复杂度较高,这个UI维护成本就非常高了。
图1.2 GUI例图
1. //代码 1:
2. // C#
3. using UnityEngine;
4. using System.Collections;
5. public class GUITest : MonoBehaviour
6. {
7. public Texture2D icon;
8. void OnGUI ()
9. {
10. GUI.Box (new Rect (10,10,100,50), new GUIContent("This is text", icon));
11. }
12. }
1.5.2 NGUI
NGUI使用树形结构组织游戏UI。并且使用了Unity定义的元素拼接UI界面。可以在不运行游戏的情况下编辑和查看UI面板。让美术和程序工作分离:美术可以把UI拼接好,做成一个Prefab提供给程序控制逻辑。如图1.3是NGUI编辑的天天飞车单局UI。我们可以直接在Scen视图中查看和编辑UI面板。这种结构,既方便美术制作UI动画,
也方便程序查找UI显示上的BUG。
图1.3 NGUI编辑UI界面
1.6 Prefabs介绍
Prefabs是一种Unity的资源类型,可以简单理解为一个预先设置好的游戏对象。我们可以把这个游戏对象创建到场景后,其结构和属性都跟我们预设一样的。
我们定义和使用Prefab的原因在于,把场景中动态创建或者需要重复使用的物件,设置成一个Prefab,我们就可以根据需要创建。创建出来的实例跟我们预设是一致的。包括模型结构以及节点的组件属性。
几乎所有的游戏对象都可以设置成一个Prefab,例如,一辆车、一个UI界面、一个武器、一颗子弹…..
Prefabs的制作很简单,我们只需要把游戏对象在Scen中编辑好后,从Hierarchy窗口把该游戏对象拖到Project窗口,改游戏对象就被保持成一个Prefab对象了。
Prefabs的实例化也很方便:
加载:GameObject goTest = Resources.Load(“TestPrefab”) as GameObject;
克隆:GameObject goTest2 = Instantiate(goTest) as GameObject;
1.7 对象池
天天飞车大部分常见的游戏对象都采用对象池来管理。对象池的特点是:
加载后不释放
不使用,放到对象池
下次用,直接从池子里取
定义最大的分配数量,控制内存
对于同一个对象,使用完成后放到指定的空节点,并且Deactive。下次使用的时候,直接从改池子里面取。池子中的对象列表为空时,允许克隆新的对象,放到池子。对于某个对象,定义一个最大的分配数量,控制内存。
图1.4 对象池处理流程图
使用对象池最大的好处就是减少了资源加载时间。当然,它同时带来了内存消耗的增加。根据游戏对象的特性,合理的设定其对象池的最大分配数量也是一个关键。可以考虑增加一个算法,把那些长时间不用的内存池释放或者减少分配的对象数量。
2 反外挂策略
手机游戏进入运营阶段,对于开发人员来说,最棘手的就是反外挂问题。天天飞车单局中没有协议交互,在游戏运行期间统计游戏数据,游戏结束把数据提交给服务器进行校验。所以,反外挂的难度相对于PC游戏来说是更加大的。
常用的反外挂策略有:
客户端的关键数据使用安全数据类型。
数据加密有很多种方法,常用的是采用数据影子进行加密。
数据统计,结算上报统计数据。
单局中没有数据交换的情况下,只能把数据统计放到客户端。关键逻辑采用多数据校验记录,外挂需要同时修改多个变量才能骗过反外挂校验。
开局数据下发,结算回带。
某些关键数据,在开局的时候,由服务器下发。并且保证游戏过程中和结算上报都使用同一数据。服务器最后对客户端回传的数据与下发的数据进行校验。
降低外挂在玩家中的声誉。
这算是一种非纯技术反外挂。游戏更新后,预留一些坑,服务器不开对应反外挂策略。当大量玩家购买外挂使用的时候,再打开对应策略,给玩家一定量的处罚。一方面,给玩家造成使用外挂的恐惧。另外一方面,降低了外挂供应商在玩家中的口碑。
最后要注意一点:对于使用Unity3D游戏引擎的项目,继承自MonoBehaviour的变量容易被外挂利用。例如,MonoBehaviour的Enable变量就可以被修改。天天飞车前段时间出现无限隐身的外挂,就是利用了这一点。当玩家进入隐身状态后,把控制隐身的脚本Disable,导致客户端无法统计隐身相关的反外挂信息。
3 配置
一个好的游戏,配置无疑是一个关键的因素。便利的配置,可以大大加快游戏开发进度。也可以一定量的减轻程序员的工作。我们在这里讨论一下天天飞车项目使用Unity3D引擎开发的各种配置方式。
在天天飞车项目里,常见的配置方法有以下几种:
文本文件
Xml文件
Excel文件
Unity场景或者Prefab中配置
天飞的配置获取和更新方式主要有三种:
版本发布时,打进安装包
从CDN服务器中拉取最新配置
服务器通过协议下发给客户端
Unity编辑器里面可以在Inspector面板上填写物件属性。通过Inspector面板,我们可以给场景中的某个物件中的组件进行编辑,编辑后的属性可以直接应用在游戏中。用户可以把Prefab实例化到场景中。暴露Prefab属性给策划,可以让策划方便地快捷的修改参数配置,并且直接重启游戏就可以看到效果。
Prefabs中配置的优点是开发方便,反馈及时。但是,同样也要注意到其维护成本高、需要随着版本更新,以及反外挂困难等特点。下面介绍一个简单的例子:
天天飞车的赛道块配置。游戏研发初期,因为还没有接入服务器,而且要保证开发速度,所以在场景中配置赛道块和NPC车的刷出逻辑数据。但是,随着游戏进入运营阶段,新版本的开发,发现这样的配置方法维护成本高,灵活性低。而且服务器读取不了这部分数据,反外挂不好做。在战车模式版本中,就需要把部分赛道块配置抽离到Excel表格配置了。
4 Unity3d 资源加载与内存管理
Unity提供多种加载和释放方式。大部分刚接触Unity的开发人员可能对这个比较难理解。这里引用一篇其他人整理的文章大概介绍一下。
原文出处:http://game.ceeger.com/forum/read.php?tid=4394
资源加载:
l AssetBundle.CreateFrom和WWW.AssetBundle
创建一个AssetBundle内存镜像
l AssetBundle.Load和Resources.Load
从AssetBundle读取一个指定名称的Asset并生成Asset内存对象。如果多次Load同名对象,除第一次外都只会返回已经生成的Asset对象,也就是说多次Load一个Asset并不会生成多个副本。
l Instantiate
Clone一个object的完整结构,包括其所有Component和子物体(详见官方文档),浅Copy,并不复制所有引用类型。
资源释放:
l Destroy
主要用于销毁克隆对象,也可以用于场景内的静态物体,不会自动释放该对象的所有引用。
l AssetBundle.Unload(false)
释放AssetBundle文件内存镜像
l AssetBundle.Unload(true)
释放AssetBundle文件内存镜像同时销毁所有已经Load的Assets内存对象
l Reources.UnloadAsset(Object)
显式的释放已加载的Asset对象,只能卸载磁盘文件加载的Asset对象
l Resources.UnloadUnusedAssets
用于释放所有没有引用的Asset对象
l GC.Collect()
强制垃圾收集器立即释放内存Unity的GC功能不算好,没把握的时候就强制调用一下
图4.1内存加载与释放
页:
[1]