怎么优化自己做的3D投影Unity3D游戏

          经过了4個月不懈的努力我和图灵教育合作的这本3D游戏开发书预计下个月就要出版了。这里MOMO先打一下广告图灵的出版社编辑成员都非常给力,尤其是编辑小花为这本书付出了很大的努力还有杨海玲老师,不然我也无法完成这本书的编写等这本书出版了大家记得买喔,哇咔咔~ 下面这篇文章是MOMO 3D游戏开发书籍中的一小段章节的修改版本,本篇文章我们将探讨一下Unity3D中如何来制作2D游戏目前市面上已经有非常成熟嘚2D游戏引擎,比如cocos2d 或cocos2d-x等并且都是免费的开发者可以直接用来制作2D游戏。然而使用3D引擎来制作2D游戏会让游戏画面更加附有立体感因为2D游戲中Z轴永远是0,而3D游戏中Z轴是可变化的

接着说说在Unity3D中制作2D游戏的原理。在Unity3D中绘制贴图的方式大致可分为两种第一种是在GUI中绘制贴图,苐二种是在网格面上绘制贴图先说说第一种,GUI主要用来制作简单的游戏2D界面比如游戏主界面中绘制的“游戏名称”、“开始游戏”、“保存游戏”、“退出游戏”一些按钮或界面中一切其它的高级控件,文本框输入框等等、GUI只能制作简单的图形化界面,因为它的渲染效率非常低它与3D世界中网格模型的渲染机制完全不一样。第二种的属于将图片绘制在3D中网格平面中它的渲染效率远远高于GUI中,在制作2D遊戏时都是将所有贴图绘制在平面模型对象之上最后用摄像机以90度垂直的角度照射这这些平面。

  下面我们开始学习在Unity3D中制作2D游戏的原理2D游戏又可以分为两种,区别是物体碰撞时带物理引擎或不带物理引擎带物理引擎就好比《奋斗的小鸟》一样,大家应该都玩过小鸟發射后下落击落其它物体将发生物理的碰撞。(我没有细看这款游戏但是我知道2D 与3D引擎都都可制作),不带物理引擎的就好比《捕鱼达囚》这种游戏游戏中碰撞都是由代码自己来完成的,经典的2D碰撞监测包括:矩形与矩形的碰撞、点与矩形的碰撞、圆与圆的碰撞等今忝这篇文章我们主要讨论第二种不带物理引擎的2D游戏。

如下图所示我们盘点一下2D游戏中必备的几个元素。

摄像机:无论是3D游戏还是2D游戏攝像机都是非常重要的属性移动摄像机即可更改屏幕中显示的内容,游戏地图的坐标永远都不会发生改变

地图:2D游戏中的地图一般是甴tile拼接而成,它可由地图编辑器生成然后将每一块tile绘制在整个贴图中最后将贴图贴在平面网格面之上即可。还有一种作法是将两个或两個以上屏幕大小平面以队列的形式排在屏幕后面当摄像机移动超出第一块面显示范围时,将它的坐标移动在第二块面后面此时地图就形成了一个排序的队列。为了让地图的效果更加完美一般地图可以由好几层来组成,比如背景层、与主角的遮挡曾、物理层等等

地图拼接:地图的排序队列中两张图应当是可以无缝拼接,这个应当是由美术来提供资源这里我就不那么细致了将远离说明白即可。

主角:咜的范围就比较广的敌人、物品等等出现在地图之上的都可以使用它。如果控制主角移动摄像机移动的同时主角也当跟随移动,并且保持屏幕中的移动比例除非摄像机无法移动,这时将直接移动主角在屏幕中的坐标 说的有点绕了呵呵,大家仔细想想哈哈。

然而上媔的一切面是由Plane面来完成

再Unity层次视图中选择摄像机对象,右侧监测面板视图中我们看看摄像机组件的一些属性如下图所示。需要注意嘚就是Projection 投影类型

          首先我们应当修改摄像机的属性,默认摄像机投影的类型是Perspective它保持摄像机以扩散的的形式照射着不利于2D平面的展示。這里我们应当选择Orthographic这样摄像机将直直的照射在显示的区域。

从侧面观察摄像机通过这两张图我相信大家应当能看懂为什么2D游戏要用Orthographic了吧,摄像机的投影类型是可以在代码中动态的修改的

//得到游戏中摄像机对象

         在代码中取得摄像机投影的区域大小,它也可以动态的修改这样就可是实现摄像机拉近与拉远的效果。根据投影区域的大小配合着整个地图的宽高来写判断条件避免移动摄像机时超过地图的范圍。

 接着我们使用代码来得到地图面的宽高这段代码写的就比较精细,因为网格面是可以缩放的首先得到网格面的宽与高,然后分别塖以缩放系数就可以得到真实面的宽与高然而Unity中的坐标是以“米”为单位。下面代码中用到了中文如果要想在编辑器中显示中文C#语言需要修改编码格式为UTF-16。JavaScript修改编码格式UTF-8或UTF-16即可

//得到面宽度的缩放比例

//得到面高度缩放比例

//原始宽度乘以缩放比例计算出真实宽度

有了摄像機照射的区域以及背景地图的宽高尺寸那么就可以在代码中编写逻辑判断条件啦。下面我们来使用简单的代码控制摄像机移动以及主角移動

//得到资源名称为down文件夹中的所有对象资源

//上、下、左、右平移主角

//超过限制帧切换贴图

//超过帧动画总数从第0帧开始

//将对应的贴图赋予主角对象,强制将资源文件转换成贴图

Resources文件夹中的down文件夹内值得注意的是,使用Resources来加载资源就必须将资源放在Resources文件夹中否则提示无法找到喔。在书中我以将人物四宫格行走动画加入在其中因为这里只是一个是示例,所以我只加载了向下行走的4帧动画我们看看资源在項目资源视图中的保存结构。

还有一个比较重要的地方就是要修改材质的shder类型因为默认的材质是Diffuse,它是不支持透明的如果材质不支持透明。主角的背景将会是白色如下图所示,这里选择Transparent/Diffuse保存为Transparent家族中的材质都是支持透明的。

最后2D游戏效果图映入我们眼帘了哦按键W、S、A、D控制摄像机移动,按键J、K、I、L、控制主角移动

 总结一下这篇文章,本文我们在多个Plane对象身上贴上材质资源再让摄像机直直的照射着它。实现2D游戏的基本原理本文没有涉及到Unity3D的物理引擎,不要紧在下章中我将向大家介绍一下Unity3D中的刚体组件与角色控制器组件如何来實现模型的物理效果包括物理引擎与3D或2D游戏的结合。另外大家一定要期待我的新书喔哇咔咔~嘿嘿。

雨松MOMO提醒您:亲如果您觉得本攵不错,快快将这篇文章分享出去吧 另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!


如果您愿意花20块钱请我喝一杯咖啡的話请用手机扫描二维码即可通过支付宝直接向我捐款哦。

pareTag (“Enemy”)”来代替“if (go.tag == “Enemy”)” 在一个內部循环调用对象分配的标签属性以及拷贝额外内存,这是一个非常糟糕的做法
4.对象库很棒,我们为所有动态游戏对象制作和使用库這样在游戏运行时间内不会动态分配任何东西,不需要的时候所有东西反向循环到库中
5.不使用LINQ命令,因为它们一般会分配中间缓器而這很容易生成垃圾内存。
所有使用编写的游戏玩法代码都是脚本代码在我们的项目中是使用Mono执行时间处理的C#代码。任何与引擎数据的通信需求都要有一个进入高级脚本语言的本地引擎代码的调用这当然会产生它自己的开销,而尽量减少游戏代码中的这些调用则要排在第②位
1.在这一情景中四处移动对象要求来自脚本代码的调用进入引擎代码,这样我们就会在游戏玩法代码的一个帧中缓存某一对象的转换需求并一次仅向引擎发送一个请求,以便减少调用开销这种模式也适用于其他相似的地方,而不仅局限于移动和旋转对象
2.将引用本哋缓存到元件中会减少每次在一个游戏对象中使用 “GetComponent” 获取一个元件引用的需求,这是调用本地引擎代码的另一个例子

只有拥有相同材質的物体才可以进行批处理。因此如果你想要得到良好的批处理效果,你需要在程序中尽可能地复用材质和物体

动态批处理操作是自動完成的,并不需要你进行额外的操作

1、       批处理动态物体需要在每个顶点上进行一定的开销,所以动态批处理仅支持小于900顶点的网格物體

2、     如果你的着色器使用顶点位置,法线和UV值三种属性那么你只能批处理300顶点以下的物体;如果你的着色器需要使用顶点位置,法线UV0,UV1和切向量那你只

5、      统一缩放尺度的物体不会与非统一缩放尺度的物体进行批处理。

7、      拥有lightmap的物体含有额外(隐藏)的材质属性比洳:lightmap的偏移和缩放系数等。所以拥有lightmap的物体将不会进行批处理(除非他们指向lightmap的同一

8、     多通道的shader会妨碍批处理操作。比如几乎unity中所有嘚着色器在前向渲染中都支持多个光源,并为它们有效地开辟多个通道

9、      预设体的实例会自动地使用相同的网格模型和材质。

参考资料

 

随机推荐