这是异名上手cocos后,正式开发上线的第一款游戏,用的引擎版本是v.2.2.0,游戏一共有6个场景,其中一个3D场景,4个2D场景,在这里做简单的一个复盘和回顾,因为需要我们平台的账号登录就不能给大家开放试玩了。

项目构建流程

目前来看暂时还没有要引入第三方构建工具的必要。除了几个配置的js和简单的css,合起来就十几K,引擎自身还支持按模块拆分,打包之后引擎也做了混淆压缩和命名hash处理,像精灵图合并和图片压缩目前也有基于引擎的成熟解决方案。另外这个游戏是属于ipad端的游戏,相对于微信小游戏和H5小游戏,一个是因为它有足够的代码存储空间,所以不涉及到资源的拆分问题,二个是因为是页游,我们假定都是在WiFi场景下使用iPad,所以它对流量的要求也没这么苛刻。因此在这个项目,我只基于引擎做了下面这几个常规处理:

  • 图片生成图集

  • 自定义发布模版

  • 图片做压缩

图集管理

图集这里我主要是利用了引擎自身提供的自动图集功能,它会把当前文件夹下的所有 SpriteFrame作为碎图资源,所以我们只需要把不同图集的资源划分文件夹,然后在文件夹下生成自动图集对象就可以了。当时在开发的时候其实我还是配套使用TexturePacker来处理一些小图集,现在回过头来看其实完全可以弃用它,自动图集能够更精简我们的工作流,想要理解这个工具的同学可以看我的上一篇文章。

自定义发布模版

针对发布后的项目,我有两个更改需求:一个就是更改网页的title,另外一个就是更换引擎加载时的logo;这块主要是可以通过自定义发布模版来是实现,复制一份打包之后的index.html,然后更换里面的logo链接和title,然后放到build-templates里面再重新打包一次就可以了。因为是原封不动地挪动build-templates里面的文件去覆盖打包之后的文件,所以在使用过程中有个问题就是当你需要打包vconsole进去的时候,你就得动手去修改模板了

图片压缩

这一块我使用了社区里面的一个插件,它 集成了pngquant 进行图片压缩,目前只能实现png压缩,先打包,然后通过工具去遍历打包之后的目录下面的图片,压缩并覆盖。另外因为我司有自己的发布系统,它对web项目有一套自己的打包和发布流程,而引擎打包之后我需要做个重命名才能走我们的发布流程,所以我还对这个插件做了二次定制,改造之后的插件界面如下,发布之前只需要在构建后,按顺序执行下面两步就可以了:

场景加载

因为这个游戏有多个场景,还有一个3D场景,所以需要专门做场景的加载。我是直接在主场景上实现的,当玩家点击在进入下一个场景的时候,通过cc.director.preloadScene去预加载下个场景,并且获取加载加载的进度,然后渲染到页面上,等到场景加载完毕之后就跳转过去。

function toPreloadScene (sceneName: string, jump: boolean = false) {cc.director.preloadScene(sceneName, (completedCount, totalCount) => {this.loadProgressBar.width = (completedCount / totalCount) * this.loadProgressBox.width;this.loadProgressLabel.string = (completedCount * 100 / totalCount).toFixed(0) + '%';}, (error, asset) => {Store.stageInfo.find((item:checkpointItem) => item.sceneName == sceneName).isLoaded = true;jump && cc.director.loadScene(sceneName);});}

具体效果如下:

尝鲜3D场景

游戏本身是针对小朋友的,玩法比较简单,这个场景的主要玩法是通过维持手指的点击频率,让玩家角色顺利到达终点????

做这个项目的时候,引擎已经开始支持3D模式,和我合作的设计师也有在私底下学习C4D,所以我们一拍即合决定尝鲜一下。我是基于v2.2.0进行开发的,这个版本对3D的支持很有限,最新的v2.3.0版本出来后,对3D的支持更好了,所以下面的经验仅供参考

模型导入

我直接把设计导出的.fbx模型拖进引擎,大部分材质就直接应用到画面上来,部分材质的绑定可能会丢失,自己手动绑定就可以了。这块的实践过程我们主要遇到下面几个问题:

  • 模型无法正常导入。这块的排查原因就是模型里面用来中文命名,把模型的中文命名改掉就可以了。

  • 相机节点无法同步。设计师其实已经在C4D里面调好了相机的视角,导进引擎之后,相机节点不会自动绑定,所以后期需要我们自己重新调整。

  • 模型太大。同样的场景,3D的模型大小可能是图片的五六倍以上,为了压缩模型可以让设计师把一些不必要的网格合并了。

渲染效果

初次导入模型之后,我们发现渲染的效果差强人意,下图左边是我们实际的效果,右边是C4D内的渲染效果

上面这张对比图可以看出几个问题:

  • 人物以及场景的渲染不到位。这个确实是我们缺乏经验,模型导出前需要设计师先给模型烘焙贴图,后面再导出,前后对比效果就能够提升不少。

  • 环境光不到位。这个没办法了,暂时只能将就

  • 没有阴影。引擎其实已经是支持设置阴影了的,但是尝试之后我们认为有无阴影对效果影响不大,所以我为了节省模型大小,就让设计师把场景上所有的东西都合并了,就没有专门去设置阴影。

还有一个问题就是2.2.0版本还不支持天空盒,但是对我们的影响不大,因为调整了相机之后,用户只能看到正前方,所以我就用了一个纯色的面板放在前面代替。

模型操控

在3D模式下调整相机视角和位置的操作是相对来说比较困难的,之前的项目中也实现过一个2.5D的场景,所以也这里也分享两个快捷键,一个就是调整物体的时候,点击住屏幕,在视图左上角会出现wasd(上下左右)的提示,可以通过键盘上wasd这四个按键来微调方向,相对来说会便捷很多

还有一个就是调整相机的角度,如果我们根据预览效果去调整相机的位置,实际操作起来有一定的麻烦,有一个隐藏的组合快捷键control+shift+f可以把我们场景编辑器的画面同步成相机的预览,它可以让我们更直观得调整相机效果

玩法实现

核心玩法就是在点击回调中动态改变玩家的位置,这里面还涉及到两个问题,多个相机的应用以及相机跟随。首先在布局的时候,Canvas节点和Main camera主要是用来显示2D物体,所以我把2D的物体都放Canvas节点下。而3D模型我会新建一个独立节点来存放,然后新建一个相机来专门拍摄3D物体。这样子我们就有两个相机了,这里需要理解一下关于相机的几个知识点:

  • 游戏引擎输出画面的时候会把多个的摄像机的图像叠加起来;

  • 摄像机会绘制属于自己渲染分组里面的物体,所以我们需要合理分组给每一个摄像机选取拍摄具体要拍摄的物体

  • 根据摄像机的成像原理,有两种模式的摄像机。在3D模式下,我们需要那种近大远小的效果,这种锥形的成像模式指的就是透视投影模式;而正交投影则适用于2D模式。

  • 摄像机有一个depth属性, depth小的先绘制到屏幕, depth大的后绘制到屏幕。2D的UI界面在游戏的最上层,所以我们要将拍摄UI摄像机的 depth调到所有相机的最高处;

  • 摄像机有—个clearFlag,如果你设置了,当他绘制画面的时候就会清理屏幕。因此我们只给第一个摄像机也就是拍摄2D的摄像机设置 clearFlag;后面拍摄3D模型的相机就不再设置了,不然会把前面摄像机绘制的内容清除掉。

然后玩家的视角跟随,我是直接把拍摄它的相机节点放到玩家节点内,这样改变玩家位置的时候,相机也就会跟着移动了

2D滑行游戏

这个游戏里面有一个场景的玩法是滑行游戏,玩家通过左右按钮控制人物的方向,在滑行的过程中需要绕过特定的障碍物,然后到达终点就算游戏结束。如下图所示:

选择参照物

滑行其实有两种是实现方式,主要看是应该选谁为参照物

  • 相机不动,画布移动(相对以屏幕为参照物)

  • 画布不动,相机移动(相对以画布为参照物)

理论上两种方式都只是参照物不同而已,最终实现的效果应该是一样的,并没有谁优谁劣,看需求而定。但是如果遇到要使用物理引擎,选择的时候需要考虑刚体的位置同步。比如父子两个元素:子为刚体,父不是,希望父移动的时候子也跟着移动,但是引擎的实现效果是父移动的时候子不动,原因如下:

  • 物理组件类似一个独立的容器,它的位置只和物理世界里面它的位置有关与非物理世界的位置变化无关。因此父动的时候,因为父不是物理组件,它在物理世界中的位置是不变的,虽然画面上父移动了,但是子是物理组件,子不会跟着动

  • 硬要动,可以让子记录一个初始位置,然后在update的时候,重设node节点的位置(覆盖其初始值),同时手动调用syncPosition来更新它在物理世界的位置。(之前实现的时候效果并不理想,但是引擎重新编译后暂时无法复现)

    onLoad () {this._pos = this.node.position;},update (dt) {this.node.position = this._pos;this.getComponent(cc.RigidBody).syncPosition(true);}

在起初调研阶段其实我有用到物理引擎,但是后来仔细一想,我的这个游戏场景其实只要使用到碰撞组件就可以了,所以就没有引入物理引擎,最终选择了相机不动,移动画布的实现。

背景无限滚动

同时因为赛道的距离可能会很长,所以背景的画布节点应该还是通过程序去动态拼接比较好,具体的实现方式其实就是很经典的轮播图。

这里有两个适配注意点,一个是背景图的高度不能是768,因为每次距离叠加之后还是会产生误差,如果刚好背景图的高度就是屏幕的高度的话,这个小误差就会产生很明显的空白间隔线,所以最好就是768是内容区,然后上下得各留10px空白像素区,这样子的话挪动背景图片的时候就不会有漏出的情况了。还有一种情况因为我的背景节点有赛道,所以我的背景节点是不能做拉伸的,因为拉伸之后就有真实检测的位置和视图不一致的情况。那就只能有一张固定大小的背景图,但是当用户屏幕宽度很长的时候,左右就会产生黑边,因此我们做了一个处理,就是底层节点做成widget拉伸的纯色的节点,然后赛道图是固定大小的图片,赛道图片的两边颜色刚好可以和纯色接壤,这样子就算用户的屏幕很宽也不会有黑白了。

检测绕过障碍物

因为游戏的玩法里面要求统计玩家绕过障碍物的次数,所以我需要精准地检测玩家是否绕过了该障碍物,前期定了两个方案,一个是划分圆形的碰撞区域,然后统计玩家经过了哪些碰撞区域。第二个方案就是把圆形的碰撞区域简化成三条射线。

目前选用技术方案二,因为射线是物理系统的一个子功能,如果引入物理系统的话会和上面的滚动方案有冲突;而且射线没有debug视图,调试起来也会比较麻烦;后面物体移动之后还会涉及到物理世界坐标和节点位置坐标的转换。所以在项目中我就使用矩形碰撞框来模拟碰撞射线,具体效果如下

其他备忘

在需求的实现过程中,我还遇到了一些比较典型的现象,也记录一下解决方案

Safari全屏模式断网后,卡死

在Safari全屏模式下,如果自动判断断网刷新或者自动跳转链接的话,是会卡死的,全屏模式无法退出,同时因为断网了,也无法刷新和跳转新网页,解决方法就是判断断网后,先手动退出全屏,然后再刷新网页和跳转链接

if (navigator.onLine === false) {cc.screen.exitFullScreen();window.location.reload();
}

Animation恢复到动画的初始状态

设置动画到第一帧的时间,再停止

this.longPressBtn.getComponent(cc.Animation).setCurrentTime(0);
this.longPressBtn.getComponent(cc.Animation).stop();

字体模糊

本质原因是因为字体的底层也是texture,它的渲染模式和画面上其他的图片的渲染模式不一致,所以在混合渲染的时候位图字体就会产生模糊现象,目前在论坛上看很多人都有反映情况但是并没有根本的解决方法

  • 如果是label 可以通过添加labelOutline 组件设置边框为0.3 来欺骗视觉

  • (推荐)无论是label 还是richText 都可以通过设置大字体,然后设置scale来达到视觉效果

    • 如果本身字号大的话可能缩放之后字体边缘会有部分被裁。

    • 如果设置了label 模式为固定宽度缩放模式的话也会有问题,因为字体变大,引擎自身会先做缩放,这个时候再叠加缩放就会更小了,因此这个时候不建议

  • 社区内也有人进行过引擎层面的尝试

打包前正常,打包后不正常

去看看项目的打包模块设置,看看有没有把对应的模块打包进去

该系列其他文章

  • 游戏引擎开发入门实践

  • 使用cocos进行2D和3D混合开发

原文链接: https://juejin.im/post/5e75f4cbe51d4526d87c949f

一个游戏多份收益,助力开发者技术精进副业挣钱,我是工程师经人:张晓衡,欢迎与我建立链接!

  • 大龄开发者,我是如何活下来的,又将怎样活下去

  • 极限开发,一个小程序打通任督二脉,加速助力开发者副业变现

  • 实战微信小游戏【球球要回家】视频开讲了!

  • 这位程序猿做了全世界程序猿都想做的事情!

  • 微信引擎插件会对小游戏带来怎样的利好?

  • CreatorPrimer 30篇教程汇总

  • Creator星球教程文章分类导航

  • 盘点Creator星球上的几大开源工具包

使用Cocos进行2D和3D混合开发相关推荐

  1. Unity制作出《超级马里奥》的2D和3D混合效果

    现在来做点别的东西.Nintendo Switch上刚推出的<超级马里奥>中,有一些关卡混合了2D和3D的画面,这种效果十分让人印象深刻.如何在Unity中实现这个效果呢? 正常情况下,摄 ...

  2. 盘点2020 | Cocos 精选 2D、3D 游戏合集

    盘点完了 2020 年 Cocos 技术和实例教程合集之后,今日C姐将为大家继续盘点2020年 #Created with Cocos# 的那些精品游戏,涵盖原生游戏.H5游戏和小游戏等,有来自大厂的 ...

  3. 新春特辑|Cocos 精品 2D、3D 小游戏合集

    今日 C 姐精选了 40+ 款基于 Cocos Creator 开发的 2D.3D 小游戏,推荐给各位开发者在春节假期休闲玩耍,也希望能通过这些小游戏,让大家更加了解 Cocos Creator . ...

  4. 【py】5个支持python的2D、3D游戏开发库

    0.Cocos2d: cocos2d是一系列开源软件框架,用于构建跨平台2D游戏和应用程序,由cocos2d-x.cocos2d-js.cocos2d-xna和cocos2d(Python)多种框架组 ...

  5. 3D游戏开发套件指南(入门篇)

    今天将介绍最新的3D游戏开发套件.不论是使用2D还是3D游戏开发套件,都可以在不编写任何代码的情况下,通过设置与拖放便能快捷的实现游戏创意. 指南简介 本指南将引导开发者设置一个空的场景,使用3D游戏 ...

  6. unity 3d游戏开发_使用Unity 5开发3D游戏

    unity 3d游戏开发 If there's one thing cooler than playing games, it's building games. 如果有比玩游戏更酷的一件事,那就是构 ...

  7. [3D游戏开发实践] Cocos Cyberpunk 源码解读-一文搞定延迟渲染管线原理与实践

    Cocos Cyberpunk 是 Cocos 引擎官方团队以展示引擎重度 3D 游戏制作能力,提升社区学习动力而推出的完整开源 TPS 3D游戏,支持 Web, IOS, Android 多端发布. ...

  8. egret3D与2D混合开发,画布尺寸不一致的问题

    egret3d的GUI目前还没有,在做3d游戏的时候没有UI可用,只能使用egret2d的EUI组件库,egret3d与egret2d混合开发,canvas3d的大小与位置与canvas2d并没有重合 ...

  9. android 实现 3d 文字,android 3d 游戏 开发 基础 第10课-2D文字显示.ppt

    <android 3d 游戏 开发 基础 第10课-2D文字显示.ppt>由会员分享,可在线阅读,更多相关<android 3d 游戏 开发 基础 第10课-2D文字显示.ppt(1 ...

最新文章

  1. R语言广义线性模型函数GLM、(Model fit and regression diagnostics)、模型充分性评估方法、使用plot函数以及car包函数
  2. Linux内核实现原子性操作cmpxchg指令的理解
  3. (一)安装docker
  4. python需要的数学基础训练答案_新编基础训练数学答案
  5. 一篇文读懂分布式系统本质:高吞吐、高可用、可扩展
  6. 获取指定目录下的所有文件名
  7. c语言指针实验报告总结,c语言指针实验报告
  8. DataGridView中实现点击单元格Cell动态添加自定义控件
  9. 有关;;;的基础小节
  10. LPC2103开发板I2C测试试验
  11. Nginx server之Nginx作为反向代理服务器
  12. php fastcgi exp,nginx +phpfastcgi 环境下 导出excel文件,超时,数据被截断问题,解决...
  13. 如何快速定位不小心暴露到全局的变量
  14. Spring Cloud Config统一管理微服务配置
  15. primal and dual linear problem
  16. 【java学习之路】数据库连接JDBC
  17. 初级商业数字营销师超级推荐
  18. java 输入输出流
  19. Fhq Treap范浩强Treap(无旋平衡树) 模板
  20. ubutnu下panel消失

热门文章

  1. Win10安装iis建议
  2. 微信群营销会存在哪些误区?
  3. RTOS内功修炼记(三)—— 内核到底是如何管理中断的?
  4. 臣妾是男女奴隶的总称 皇帝的女人不该如此自称
  5. C语言—atoi()、itoa()函数以及my_atoi()、my_itoa()函数详解
  6. 水滴os 鸿蒙,华为鸿蒙OS强势来袭:2K水滴屏+麒麟985+5500mAh 华为巅峰之作
  7. python读取excel公式计算结果为none_python读取excel保存公式无法读取
  8. MySql报错:1366-incorrect string value:'\xE8\x80\x8c\xE6\x88\x91' for column 'title' at row 1
  9. 怎样获取苹果手机的mac 地址
  10. web前端期末大作业 html+css+javascript化妆品网页设计实例 企业网站制作