前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Cocos游戏开发入门最佳实践

Cocos游戏开发入门最佳实践

作者头像
异名
发布于 2020-06-09 07:25:17
发布于 2020-06-09 07:25:17
1.3K00
代码可运行
举报
文章被收录于专栏:异名异名
运行总次数:0
代码可运行

因为公司的业务需求,近期学习了CocosCreator这款游戏引擎的开发,也基于此上线了一款游戏,因此写这系列文章记录一下我从入门到项目发布的学习过程。

相对于web开发,像CocosCreatoregret这种界面化的游戏引擎最大的区别就是可视化的UI编辑,以及像动画编辑、物理引擎、资源管理系统等一系列高度封装集成的工具集。所以第一篇文章我主要会介绍一下我从web端开发转向游戏开发这个过程中,我对cocos的工作流程的一些认识。尽管文档上有介绍但是新手上路,很多东西一开始被我忽略掉了,随着项目的进展,我断断续续地从文档、社区中学到了一些能提高效率的小方法和配置,在此记录一下,主要给其他新人做参考

熟悉编辑器

因为游戏的界面编辑都是通过编辑器来完成的,所以编辑器的一些基本功能和操作说明我们需要通过文档去理解熟悉,我这里会记录几个我新建一个项目必须会用的设置

配置项目设置

在开始做项目前,别忘了要在项目-项目设置中先设置下面几个配置,后续的新建场景都会默认使用这些配置,后面就不需要每建一个场景都要设置一下了

  • 初始预览场景(指定某一个场景/当前打开场景),我一般设置后者
  • 设计分辨率,引擎默认的是960*640
  • 适配模式(fit-height/fit-width)

调整编辑器布局

在工作中,因为我们绑定资源、脚本和变量的过程都是通过把它们拖拽到属性面板来实现的,而引擎的默认启动界面把属性面板放到最右侧,那当我们需要绑定操作的时候就需要把物体从最左侧面板拖拽到最右侧面板,其实这段超长的操作距离是非常影响效率的,所以大部分的开发者其实都会选择经典布局,像下图这样,把属性面板通过拖拽放在左侧和层级管理器放在一起,这样绑定变量和资源的操作效率就会相对高一点

熟悉常用的界面快捷键

CocosCreator的快捷键支持是比较弱的,但是它还是提供了几个高频操作的快捷键,通过这四个快捷键我们能快速切换这四个高频工具,很大地提高效率

  • W 移动工具
  • E 旋转工具
  • R 缩放工具
  • T 矩形变换工具

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

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

UI开发

和web端的开发不一样,cocos的UI是不用写样式的,界面上所有的元素都是用图片堆积起来的,对我来说这个转变过程挺有意思的,把样式编写去掉了可以省掉我们一些布局的时间,我在开发项目过程中也发现了一些比较好的实践方法

精准还原设计稿的窍门

因为我们在可视化的编辑器中都是通过拖拽来实现图片的定位的,我们不写样式文件。但是我在第一个项目的时候思维又还没转换过来,还是习惯web端那种开发模式,我每次布局的时候都会去翻一下设计稿,测一下物体的位置,然后再在属性面板上输入正确的position信息,这样做当然是没问题的,但是效率真是太低了,后来我看到一位前辈的开发过程后才恍然大悟,改正过来。他是这样做的,在设计稿那里截一张完整的界面图,然后把它当成一个底层的节点,这样子我们就有一个和设计稿一模一样的背景图了,我们布局的时候再把一个个物体放到它正确的位置上,完事之后只需要把那个底层的节点删除就可以了,这样子布局的的效率提升可是质的飞跃。

把UI按模块拆分管理

在项目中,我们的一个场景里面的内容可能会很多,比如我这个场景里面有N个弹窗,如果我们把所有的弹窗的内容按他们的真实位置塞到canvas节点中,那真的是一件很糟糕的事情,因为一个个物体们会重叠在一起,后期我们将很难进行选中操作。所以我们在做UI管理的时候需要一个窍门就是把UI按模块拆分,并且移位管理,如下图

我并不会把弹窗一和弹窗二的内容叠加到主界面上,当然一开始我们可以这样做,因为我们可能需要根据背景图来确定每个物体的位置,但是当我们完成布局之后,可以像我一样把他们的父节点移出主界面之外,我这里的父节点是通过widget做了拉伸的,完全适配窗口的大小,当父节点被移出其实就是position做了偏移,后续在代码里面控制弹窗出现的时候,我们只需要多写一行代码,把父节点的position设置为(0,0)就可以了。这样子在后续维护的过程中我们的UI界面也能一目了然。如果用了widget,也别忘了在代码调用的时候去手动更新widget的位置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
let widget= this.mapDlg.getComponent(cc.Widget);
widget.right = 0;
widget.left = 0;
widget.updateAlignment();

利用好自定义控件

自定义控件库其实就是给常用的prefab增加了一个入口,当然可以直接把prefab拖拽到层级管理器里面直接用,但是其实还是一个效率的问题。当你的prefab多了之后,先不说你要去翻资源管理器里面的文件夹,当你打开prefab所在的文件夹之后,一眼看过去是比较难找到自己需要的控件的,自定义控件不仅仅额外给了一个入口,而且它可以给prefab增加一个图标和控件名称,对高频的复用控件的使用来说,这真的太有必要了,打开面板一下就能找到你所需要的控件然后直接拖拽使用了

代码开发

配置Vscode

虽然这块文档里面有写,但是因为我是从写web端转来做游戏的,以为自己很熟悉vscode,又因为项目的原因要急于上手就选择性地忽略了这一块,仅仅只使用了代码提示这个工作流,等到看到社区内的前辈们的日常操作之后,才发现配置好vscode的工作流其实也是一大效率神器,它包括四块东西

  • 代码智能提示
  • 设置文件搜索范围
  • 手动触发编译
  • 配合Chrome debug插件在编译器内debug

代码提示和文件搜索我就不提了。在正常情况下我们修改了代码,只有回到cocos界面才能触发项目实时热更新,而我们在vscode上配置好编译的task,并且设置启动task的快捷键,我设置的快捷键是cmd+r,我们就可以在vscode上通过快捷键触发项目的热更新,它可以让我们在写代码的时候更专注在代码上;具体的配置步骤可以查看文档

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// .vscode/tasks.json
// 配置vscode任务
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "compile",
            "command": "curl",
            "args": ["http://localhost:7456/update-db"],
            "type":"shell",
            "isBackground": true,
            "group": "build",
            "presentation": {
                "reveal": "always"
            },
        }
    ]
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// User/keybindings.json
// 配置任务启动快捷键
[
    {
        "key": "cmd+r",
        "command": "workbench.action.tasks.runTask",
        "args": "compile"
    }
]

还有一个就是ChromeDebug插件,这块的流程只在1.9.0的文档中才有,后续的文档中虽然能搜索出来,但是无法阅读,它支持你在vscode中唤醒Chrome,并在vscode中进行debug,也是一大效率神器

参数绑定

在处理复杂界面的时候,因为页面上的元素较多,就算我们尽可能地拆分脚本,但是在一个脚本里面需要绑定的变量还是不可避免的增多,然后代码里面就会有一大串@property声明的变量,所以新手们需要充分利用的类型,比如我有10个只是单纯用于的显示和隐藏的node节点,就可以通过声明一个node数组节点来绑定,这样子我在代码里面显式声明的变量就会少很多?

还有一种常见的情况就是一个物体它有两种甚至多种状态,当我刚上路的时候我对cocos的内置对象还不熟,然后因为我们界面上的基本组成单元是sprite图,我就做了一个很蠢的操作就是有多少状态我就创建多少sprite节点,状态切换的时候就切换相应节点的显隐。但是这种情况下其实好的做法是通过一个spriteFrame的数组变量去存储不同状态的spriteFrame然后状态切换的时候去更新相应的spriteFrame:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@property([cc.SpriteFrame])
btnStatus: cc.SpriteFrame[] = [];

// 切换不同的状态
this.node.getComponent(cc.Sprite).spriteFrame = this.btnStatus[0];
this.node.getComponent(cc.Sprite).spriteFrame = this.btnStatus[1];
this.node.getComponent(cc.Sprite).spriteFrame = this.btnStatus[2];

当然这样也不是最佳实践,因为后续接手我们代码的人通过代码根本就看不出数组不同下标对应的spriteFrame是哪一个,他还得通过界面去查看绑定的资源。所以最佳的实践应该是把该一个物体不同状态图片生成图集,图集里面的每个图片可以精确命名,当需要切换状态的时候,我们就可以通过精确的名称获取到对应的spriteFrame,虽然这样子我们就需要多维护一个图集,但是它是一个相对更规范的实践方式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@property(cc.SpriteAtlas)
spacemanAtlas: cc.SpriteAtlas = null;

// 切换不同的状态
this.body.getComponent(cc.Sprite).spriteFrame = this.spacemanAtlas.getSpriteFrame("take_off_state");
this.body.getComponent(cc.Sprite).spriteFrame = this.spacemanAtlas.getSpriteFrame("ready_state");
this.body.getComponent(cc.Sprite).spriteFrame = this.spacemanAtlas.getSpriteFrame("rest_state");
this.body.getComponent(cc.Sprite).spriteFrame = this.spacemanAtlas.getSpriteFrame("fire_state");

第三方工具

我目前用到的第三方工具主要有这下面几个

利用 Texture Packer 生成图集

虽然引擎在打包阶段给我们提供了自动合图功能,但是为方便资源的维护、代码变量的管理以及后面性能优化上很重要的drawcall优化处理等等,我们还是很有必要在开发阶段就要有意识地去做图集管理。

ShoeBox

异常强大的ps插件,我目前用得最多的就是拆分图集、gif图拆解、生成位图字体、合成gif图,它也可以合成图集,但是我觉得Texture Packer在这方面更好维护。拆分图集、gif图拆解这两个功能我主要用来获取一些游戏的公共资源,最简单的像一些金币的动画,我需要它的序列帧,如果设计师那边有现成可用的固然好,如果没有的话特意让人家去做一份也没有很大的必要,我比较常去爱给网翻一些CC0版权的资源来用。比如下面我需要用到一张合图里面的某一张图片,我就会利用ShoeBox拆分合图

游戏当中不可避免的会用到一些卡通点的字体,比如数字由0到9组成,是我们设计师独出心裁设计的,需要应用到游戏当中。应该会有部分的前端像我一样是做web开发的,以前没有接触过游戏开发,那要实现这个需求就一脸懵逼,总不能让我用一个个sprite去代替吧。其实还真的是,位图字体的做法就是将会使用到的每个文字对应的字体做成位图,生成文字内容和位图的映射,游戏中动态的调用显示位图。这样即在游戏中呈现了漂亮的字体,又节省了资源。位图字体是由一张png的图片集和一个fnt配置文件组成的。其中png图片集中包括了所有会使用到的位图,fnt配置文件里描述了这些位图应该怎么从png图片集中切分出来。下面就是利用ShoeBox制作位图字体的过程

Sketch

我司的设计工具,之前做web端开发的时候我和设计师的交付都是通过sketch的导出的网页或者通过蓝湖,但是做了游戏项目之后,我发现开发这边对稿子的调整还是挺多的,当稿子已经基本交付过来之后,我们这边有小的调整的话能够自己搞定的话,也没必要再去麻烦人家,所以像切图、去色、通过变换工具减少九宫格图片的多余面积等一些基本又高频的操作能不麻烦设计师就自己搞定吧,同时还有一些特殊交互动画需要对切图有一定的拆分处理,如果自己能搞定的话也能省去沟通以及交付的成本

字蛛

这个其实用得相对低频,还是回到游戏中的字体需求,如果我希望界面上的用的字体比较符合整个UI的风格,比如我要一个圆体,但是用户的系统字体默认是那种瘦体,UI上看起来肯定是体验不好的,设计师同事也不可能给每个字都做成位图字的,圆体中文字体库起码几M以上,我们又不可能全部当成资源引入,所以我们需要做字体库的切割,我们的游戏里面用到哪些字就用只提取那些字,切割后的字体库只有几k,那就可以满足我们的生产环境使用了,具体的用法可以去官网查看。因为每次都需要启动服务,我很早之前嫌麻烦做过一个小工具(Mac下载,window下载),下面基于它做一个演示

总结

以上就是这篇文章的全部内容了,主要记录一下我从新手开始做游戏开发后,一些后知后觉才学会的能够提高工作效率的工作流和配套小工具,因为是在公司内做第一个螃蟹的人,团队内部还没有这块的沉淀,加上这些小经验要么在文档中被我忽略而过,要么就零零散散在论坛中,所以后面会尝试做一些小结沉淀下来,后面我如果发现还有别的能提高效率的工作流程我也会在这里更新。除了上面这些新手上路的絮絮叨叨外,还有一些在真实项目中遇到的坑以及解决方案,我也觉得比较有意思,后面也会尝试做成一系列的总结沉淀下来,让我们不见不散

原文地址:https://juejin.im/post/5e6dead05188254903695bbd

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 异名 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Android事件分发原理分析
在Android中,触碰控件的时候回产生一个ACTION_DOWN事件并逐层向下传递,首先ACTION_DOWN回先从Activity的dispatchTouchEvent方法开始向下传递:
大大大大大先生
2018/09/04
1.3K0
Android事件分发原理分析
class和getClass()的区别
前几天做项目,觉得自己都开发一年多了,还没有自己封装的类,感觉真是白做了,再加上,看到自己的代码,我都不忍心看,有的时候,还需要自己去读自己写的代码,乱乱糟糟的,实在不忍心看,没办法,重现在开始吧,把自己需要的,都封装起来,用到什么的时候,在哪来用,方便,快捷
全栈程序员站长
2022/07/02
4320
android 自定义登陆对话框基类封装,且随着软键盘的弹起自动移动位置
像对话框这种常用的组件,用过一次最好做个封装。再次用到时就很简单啦。直接拿过来复用即可。
杨永贞
2020/12/01
7400
android 自定义登陆对话框基类封装,且随着软键盘的弹起自动移动位置
Android完美解析setContentView 你真的理解setContentView吗?「建议收藏」
说到Activity的setContentView,咱们直接找到一个Activity中的setContentView点进去看看!
全栈程序员站长
2022/09/13
1.6K0
Android Studio 知识储备 之 ✨-基础知识学习历程
所有的资源文件都会在R.java文件下生成对应的资源id,我们可以直接通过资源id访问到对应的资源。使用mipmap会在图片缩放在提供一定的性能优化,分辨率不同系统会根据屏幕分辨率来选择hdpi,mdpi,xmdpi,xxhdpi下的对应图片,所以你解压别人的apk可以看到上述目录同一名称的图片,在四个文件夹下都有,只是大小和像素不一样而已!当然,这也不是绝对的,比如我们把所有的图片都丢在了drawable-hdpi下的话,即使手机 本该加载ldpi文件夹下的图片资源,但是ldpi下没有,那么加载的还会是hdpi下的图片! 另外,还有一种情况:比如是hdpi,mdpi目录下有,ldpi下没有,那么会加载mdpi中的资源! 原则是使用最接近的密度级别!另外如果你想禁止Android不跟随屏幕密度加载不同文件夹的资源,只需在AndroidManifest.xml文件中添加android:anyDensity="false"字段即可!
呆呆敲代码的小Y
2021/08/12
6710
Android实现仿支付宝流水
今天给大家讲的是如何自定义下拉的ListView实现支付宝账单的效果,月份是需要悬浮的,然后没一个月归为一类,先看一个效果图吧。 场景:后台下发的数据就是一个List<对象>,考虑到实际情况,还需要做
xiangzhihong
2018/02/06
1.3K0
Android实现仿支付宝流水
Android常用对话框大全——Dialog「建议收藏」
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/137960.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/23
4.3K0
Android常用对话框大全——Dialog「建议收藏」
Android开发笔记(四十五)手势事件
基本的手势事件主要有如下三个方法: dispatchTouchEvent : 判断该事件是否需要下发。返回true表示需要下发给下级视图,返回false表示不需要下发(交给自身的onTouchEvent处理)。但是否最终下发,还需根据onInterceptTouchEvent的拦截结果。 onInterceptTouchEvent : 判断当前容器是否需要拦截该事件。返回true表示予以拦截(交给自身的onTouchEvent处理)、不放给下级视图,返回false表示不拦截该事件。 onTouchEvent : 判断该事件是否处理完毕。返回true表示处理完毕,则无需处理上级视图的onTouchEvent,一路返回结束流程。返回false表示该事件未完成,则返回继续处理上级视图的onTouchEvent,然后再根据上级onTouchEvent的返回值判断是直接结束还是由再上级处理。
aqi00
2019/01/18
1.3K0
Android开发笔记(九十四)图片的基本加工
Android上的图形使用Drawable类,而位图管理则使用Bitmap类,java上与之对应的是awt包中的BufferedImage。Android开发中有需要对jpg、png文件进行加工的,都是操作Bitmap,下面是Bitmap类的常用方法说明: compress : 根据设定的位图格式与压缩质量,对图片进行压缩。 recycle : 回收位图对象资源。 createBitmap : 从源图片中裁剪一块位图区域。 createScaledBitmap : 根据设定的目标大小,对源图片进行缩放。 getByteCount : 获取位图的字节大小。 getWidth : 获取位图的宽度。 getHeight : 获取位图的高度。
aqi00
2019/01/18
7750
Android点击其他地方隐藏键盘
Android点击其他地方隐藏键盘 1.第一种:隐藏页面一进来EditText获取焦点就弹出软键盘 在oncreate()里调用如下方法即可 /** * 隐藏软键盘 */ private void hideSoftKeyBoard() { getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
程序员飞飞
2020/02/27
3.3K0
Robotium DialogUtils「建议收藏」
package com.robotium.solo; import android.app.Activity; import android.content.Context; import android.os.SystemClock; import android.view.ContextThemeWrapper; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.EditText;
全栈程序员站长
2022/09/16
2910
点击空白处隐藏软键盘
在点击Editext的时候安卓会弹出软键盘,在我们输入完后不点击软键盘的”完成”键的时候,软键盘有时候会一直停留在”界面”,甚至跳转到另一个”界面”上.这样体验上不是很好.所以点击非EditText区域上,让软键盘隐藏起来是一种可行的方案. 从别人的博客上看到的代码,摘录如下:
夏洛克的猫
2018/10/18
1.6K0
Android点击EditText文本框之外任何地方隐藏键盘的解决办法
1,实现方法一:通过给当前界面布局文件的父layout设置点击事件(相当于给整个Activity设置点击事件),在事件里进行键盘隐藏 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/traceroute_rootview" android:layout_width="fill_parent" android:layout_height="fi
庞小明
2018/03/07
1.6K0
Activity 事件分发
首先先判断当前事件是否是Down事件,如果是就调用onUserInteraction方法,如果不是就不会调用,所以Up,Move方法不会调用该方法。
Yif
2019/12/26
8820
【云+社区年度征文】探究 | 如何捕获一个 Activity页面上所有的点击行为
既然我要捕获点击事件,首先就想到的是通过事件分发机制,也就是在源头就去获取所有的触摸事件,然后对点击事件进行统计,干吧~
码上积木
2020/12/03
1.1K0
相关推荐
Android事件分发原理分析
更多 >
LV.0
深圳市梅沙科技有限公司前端开发工程师
作者相关精选
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验