☰
Cocos Creator打包微信小游戏:从构建配置到二次开发实战
2026/10/19 2:19:30 网站建设 项目流程

简介:这是一份 Cocos Creator 打包微信小游戏的完整源代码资源,适合已掌握 Cocos Creator 基础、正准备将自己的 2D 游戏发布到微信小游戏平台的开发者。压缩包共 592 个文件,约 1.67MB,包含 289 个 json(场景、配置与资源映射)、180 个 png(美术素材)、81 个 meta(资源导入信息)、17 个 js 与 2 个 ts(核心逻辑与脚本)、2 个 fire(场景文件)以及 bin、plist、fnt、gltf 等资源,基本覆盖小游戏从配置、构建到运行所需的典型文件结构。已有 3301 人学习下载。通过这份资源,可以直观了解 Cocos Creator 构建微信小游戏时引擎自动生成的目录组织方式、资源引用关系和脚本入口,减少首次打包时在平台配置与文件校验上花费的调试时间,适合作为入门参考或同类项目打包时的对照样例。

1. 先说结论:这份小鸟源码真正值钱的是打包链路

拿到一份“Cocos Creator 打包成微信小游戏源代码”,不少人第一反应是先打开 Cocos Creator 跑一遍:一只像素小鸟立在屏幕左侧,点击屏幕上升,穿过水管缝隙就加分,碰到水管或地面直接结束。跑通了,有人会想“这不就是个休闲小游戏 demo 吗”。然后他按自己的理解构建发布,导入微信开发者工具,黑屏、报错、场景加载不出来,折腾一下午才发现——这份源码里最有价值的不是那只扇翅膀的鸟,而是从 Creator 工程到微信小游戏产物之间一整套已经调通的配置。

这份资源适合两种人:一是想在微信小游戏里做经典“点击上升”玩法、却被构建配置卡住的新手;二是已经会写 Cocos Creator 游戏逻辑、想搞清楚小游戏平台适配细节的开发者。把它跑起来,等于拿到一个可以照着抄的模板:场景怎么配、脚本怎么挂、资源怎么压缩、构建参数怎么选,全都在工程里摆好了。

2. 工程解剖:Cocos Creator 项目里哪些文件在替小游戏打工

拿到这份工程,先别急着打开场景,把目录过一遍,你就能看出它跟普通 Creator 教学项目的差别:普通项目只有 assets 和脚本,这份工程多了一整套围绕微信小游戏平台做的构建适配。

2.1 技术栈选型:为什么是 2.4 系 Creator 加 TypeScript

工程用的是 Cocos Creator 2.4 系构建流程,脚本层是 TypeScript。选这套组合不是拍脑袋:2.4 时代 Creator 对微信小游戏的支持已经稳定,构建产物是纯 JS 加 JSON 配置,首包体积容易控制;而 3.x 虽然也在小游戏平台跑得不错,但构建产物体积偏大,对包体限制更敏感。

物理相关代码没有引物理引擎,全部用手动模拟。这个选择在小游戏场景里非常务实——物理引擎库打进包体要占几百 KB,手机端性能开销也不小,而这类“点击上升”玩法的碰撞判定用矩形相交就足够。我一般拿到这类休闲游戏源码,也会先问一句:物理引擎是不是必要的?很多情况下答案都是否定的。

2.2 assets 目录结构:游戏资源和脚本怎么分区

打开工程根目录,核心结构是这样的:

assets/ scenes/ # 场景文件 loading.fire # 启动场景,负责预加载和初始化 game.fire # 主游戏场景,玩法全在这里 scripts/ # 逻辑脚本 Bird.ts # 小鸟控制:重力、跳跃、旋转 PipeManager.ts # 水管生成、移动、回收 GameManager.ts # 状态控制、碰撞、计分 AudioManager.ts # 音频加载与播放 textures/ # 图片资源 bird/ # 小鸟序列帧,扇翅动画用 pipe/ # 上下水管图片 background/ # 背景、地面 prefabs/ # 预制体 Bird.prefab # 小鸟预制体 Pipe.prefab # 水管对预制体 build/ wechatgame/ # 微信小游戏构建产物,由 Creator 生成

assets 是编辑器的资源根目录,Creator 会按这个目录结构管理资源 UUID 和依赖。scenes 和 prefabs 分开放是工程里的常见做法,便于预览场景时快速定位;scripts 单独成目录也方便脚本编译时按依赖关系打包。

textures 里的小鸟和背景都是小尺寸图,这是故意控制的。微信小游戏主包有体积限制,图片资源是首包体积的大头,能用小图绝不用大图。水管和地面用纯色拼接,配合简单纹理,比整张背景图省得多。

2.3 build/wechatgame:构建产物里藏着平台适配的关键

构建发布一次后,build/wechatgame 目录下会出现这些文件:

build/wechatgame/ game.js # 编译后的游戏逻辑代码 game.json # 小游戏全局配置:方向、子包等 project.config.json # 微信开发者工具的项目配置 src/ # 引擎源码和设置 assets/ # 序列化后的场景与资源

project.config.json 是微信开发者工具识别项目用的,里面配置了 appid、项目名、编译设置。game.json 是真正跑在微信小游戏环境里的运行时配置,deviceOrientation 字段控制了屏幕方向,networkTimeout 字段决定了网络请求超时时间。

这里有个细节值得注意:构建产物里 assets 目录里的资源全部是重新序列化过的,已经不是编辑器的原始格式。所以在微信开发者工具里改了 game.js 之后,如果重新在 Creator 里构建,改动会被覆盖。二次开发时要么改 Creator 源码再构建,要么只改产物里 Creator 不会动的文件——这个坑后面会细说。

3. 打包实战:从 Creator 构建到微信开发者工具的三步流程

这一章直接把打包流程完整走一遍。这三步听起来简单,实际每一步都有几个参数容易配错,配错了预览就是黑屏。我按实际操作的顺序来写。

3.1 构建面板关键配置:平台、方向、分辨率

打开 Creator 菜单栏的“项目” → “构建发布”,在构建面板里选择微信小游戏平台。核心配置项有四个:

配置项推荐值说明
发布平台微信小游戏对应构建产物目录 wechatgame
设备方向竖屏 portrait这类玩法横屏没法玩,竖屏最合适
设计分辨率720 × 1280主流竖屏分辨率,切到不同手机上不会被过度拉伸
勾选 ES6 转 ES5开启兼容低版本微信基础库,不勾选会在老机型上报语法错误

设计分辨率这个参数要重点说。720 × 1280 是按竖屏主流机型取的,构建后游戏画面会被缩放适配到实际屏幕。如果设计分辨率太高,小屏手机上 UI 会显得特别小;太低,在 2K 屏上又会有明显颗粒感。这个工程在适配模式上用的是适配屏幕宽度加适当地图高度,保证玩家在任何机型上看到的画面范围接近一致。

3.2 构建与导入:生成产物到微信开发者工具

配置完成后点击“构建”,Creator 会把 assets 里的资源序列化、脚本编译打包,最后生成 build/wechatgame 目录。构建完成后,打开微信开发者工具,选择“小程序”项目,目录直接指向 build/wechatgame 就好。

导入后建议先做两件事:

第一,在微信开发者工具的“详情” → “本地设置”里勾选“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书”。开发阶段资源请求如果走了远程地址,不勾这个会被拦截。

第二,在主界面确认 game.js 里的渲染逻辑没有报错。常见错误是 require 路径不对,或者脚本里用了 ES6 的箭头函数但构建时没做语法转换,错误信息会直接指向具体行号。

3.3 调试预览:真机效果和模拟器效果差距在哪

微信开发者工具自带模拟器,但模拟器和真机行为不一致,主要体现在三方面:

一是屏幕适配。模拟器窗口默认是 iPhone 尺寸,真机可能有刘海屏、挖孔屏、全面屏,安全区不同,画面底部可能会被系统手势条遮挡。这个工程在 GameManager 里读取了 safeArea,后续适配章节再展开。

二是性能表现。模拟器用的是电脑性能,真机是手机性能。如果游戏在模拟器上流畅,真机上掉帧,优先检查是否有对象反复创建销毁——水管对如果每根都新建节点,到后期水管数量多了就会卡。这个工程里用了对象池,就是解决这个问题的。

三是音频策略。微信小游戏平台规定音频不能自动播放,必须由用户触摸事件触发。模拟器上自动播放可能正常,真机上没声音大概率是触发了这个限制。

3.4 除了编辑器,还有命令行构建方式

如果后续要反复构建调试,我建议直接用命令行构建,省去打开编辑器点按钮的时间。Cocos Creator 支持命令行构建:

# macOS 路径示例 /Applications/CocosCreator/CocosCreator.app/Contents/MacOS/CocosCreator \ --project /path/to/your/project \ --build "platform=wechatgame;debug=true" # Windows 路径示例 C:\CocosCreator\CocosCreator.exe \ --project D:\path\to\project \ --build "platform=wechatgame;debug=true"

命令行构建走的构建逻辑和编辑器里一致,区别是 debug=true 时构建产物保留源码映射,方便在微信开发者工具里调试脚本;正式发布时把这个参数改成 false,产物体积会小一些。

4. 核心代码拆解:小鸟飞行、水管生成与碰撞判定

这一章直接拆玩法代码。整个玩法逻辑可以拆成三块:小鸟自身的行为、水管的生成与移动、两者之间的碰撞与计分。每一块都能单独替换和扩展,这正是这份源码适合二次开发的基础。

4.1 小鸟控制:手动重力模型怎么模拟出飞行手感

小鸟的核心代码在 Bird.ts,下落和上升完全手动计算,没有依赖物理引擎:

// Bird.ts —— 手动模拟重力,不依赖物理引擎 const { ccclass, property } = cc._decorator; @ccclass export default class Bird extends cc.Component { @property jumpSpeed: number = -320; // 点击时瞬间速度,负值表示向上 @property gravity: number = 900; // 每秒钟加速度增量,像素/秒² @property maxRotation: number = 30; // 最大旋转角度,让俯冲姿态不过度夸张 private vy: number = 0; // 当前垂直速度 private isDead: boolean = false; update(dt: number) { if (this.isDead) return; // 重力累积到速度上,速度再累积到位移 this.vy += this.gravity * dt; this.node.y += this.vy * dt; // 根据速度方向让小鸟低头或抬头,增加姿态反馈 const ratio = Math.max(-1, Math.min(1, this.vy / 500)); this.node.angle = ratio * this.maxRotation; } jump() { if (this.isDead) return; this.vy = this.jumpSpeed; this.node.angle = this.maxRotation; } die() { this.isDead = true; } }

逻辑说明:每帧经过的时间 dt 是一个增量值,单位是秒。重力加速度乘以 dt,得到“这一帧速度增加了多少”;速度乘以 dt,得到“这一帧位移了多少”。这是 2D 平台游戏里最经典的手动重力写法,比接入物理引擎更可控。

参数说明:jumpSpeed 是负数,因为 Cocos Creator 坐标系里 y 轴向上为正,负值代表向上飞。这个值绝对值越大,点一下就蹿得越高。gravity 越大,下落越快,手感就越“重”。两个参数配合决定了这游戏的难度曲线,后面二次开发部分会讲怎么调整。

旋转那段用了 ratio 做限幅,把速度映射到 -30 到 30 度之间,防止小鸟下落时翻个底朝天。

4.2 水管生成:对象池是怎么保证不掉帧的

水管生成在 PipeManager.ts。这里最关键的设计不是每隔几秒生成一对水管,而是生成的节点“循环利用”:

// PipeManager.ts —— 水管对对象池,避免频繁创建和销毁节点 const { ccclass, property } = cc._decorator; @ccclass export default class PipeManager extends cc.Component { @property(cc.Prefab) pipePrefab: cc.Prefab = null; @property spawnInterval: number = 1.5; // 生成间隔,秒 @property gapHeight: number = 220; // 上下水管之间的空隙高度 private pool: cc.Node[] = []; // 对象池,最多存 8 对 private timer: number = 0; start() { // 预创建 4 对水管放进池子,游戏启动时不卡顿 for (let i = 0; i < 4; i++) { const pipe = cc.instantiate(this.pipePrefab); pipe.parent = this.node; pipe.active = false; this.pool.push(pipe); } } update(dt: number) { // 生成计时器 this.timer += dt; if (this.timer >= this.spawnInterval) { this.timer = 0; this.spawnPipe(); } } spawnPipe() { // 从池子里取一对;池子空了就新创建 let pipe = this.pool.find(p => !p.active); if (!pipe) { pipe = cc.instantiate(this.pipePrefab); pipe.parent = this.node; this.pool.push(pipe); } pipe.active = true; // 随机设置水管对的 y 位置,让空隙位置变化 const minY = 120; const maxY = 360; pipe.y = minY + Math.random() * (maxY - minY); pipe.x = 400; // 屏幕右侧外进场 } }

逻辑说明:start 里先创建 4 对水管但不激活,这些节点提前存在于场景中,后面的游戏过程就是循环激活和复用。spawnPipe 从池里找一个未激活的节点,设置新的位置后激活。这样游戏玩 10 分钟,也就只有那十几对节点在反复移动,不会有新节点产生导致的卡顿。

参数说明:spawnInterval 越小,水管出得越快,游戏整体节奏越快。gapHeight 是上下水管之间的空隙,越小越难钻过去。这两个参数一个管时间压力,一个管操作难度,是游戏难度曲线的两个主要旋钮。

random 范围那两行,minY 和 maxY 控制水管对的位置变化范围。范围越大,玩家每次钻缝都要重新找位置,视觉上不容易产生重复感。

4.3 碰撞判定与计分:矩形相交和分数存储

碰撞检测没有用物理碰撞体,而是用坐标盒的直接相交判断,放在 GameManager.ts:

// GameManager.ts —— 状态管理、碰撞检测、计分 const { ccclass, property } = cc._decorator; @ccclass export default class GameManager extends cc.Component { @property(cc.Node) bird: cc.Node = null; @property(cc.Node) pipeManager: cc.Node = null; private score: number = 0; private isGameOver: boolean = false; update() { if (this.isGameOver) return; // 遍历水管对,逐个做矩形框碰撞检测 const pipes = this.pipeManager.children; for (let i = 0; i < pipes.length; i++) { const pipeNode = pipes[i]; if (!pipeNode.active) continue; if (this.checkHit(this.bird, pipeNode)) { this.gameOver(); return; } // 计分逻辑:水管完全越过小鸟后加分 if (pipeNode.x < this.bird.x && !pipeNode.getComponent('Pipe').scored) { pipeNode.getComponent('Pipe').scored = true; this.score++; } } } checkHit(a: cc.Node, b: cc.Node): boolean { const boxA = a.getBoundingBoxToWorld(); const boxB = b.getBoundingBoxToWorld(); return boxA.intersects(boxB); } gameOver() { this.isGameOver = true; this.bird.getComponent('Bird').die(); // 写入微信小游戏本地存储,保留下次启动的最高分 if (typeof wx !== 'undefined' && wx.getStorageSync) { const best = wx.getStorageSync('bestScore') || 0; if (this.score > best) { wx.setStorageSync('bestScore', this.score); } } } }

逻辑说明:getBoundingBoxToWorld 取的是节点在屏幕坐标里的轴对齐包围盒,intersects 就是两个矩形是否相交的判断。这套组合适合所有 2D 休闲游戏,不需要物理引擎参与,性能开销极小。

计分方式用的是“水管通过小鸟后置位”,每对水管只记一次分。这里通过 Pipe 组件上的 scored 布尔值避免重复计分,比用坐标区间判断更可靠。

微信存储那部分做了环境判断:typeof wx !== 'undefined',这样代码在 Creator 编辑器预览里也不会报错,只有真正跑到微信小游戏环境里才执行存储逻辑。

4.4 平台桥接:wx 全局对象在代码里怎么用才安全

除了解析存储分数,工程里 AudioManager 也做了类似的环境判断。因为音频必须先由用户触摸触发,所以在场景初始化时会把音频播放挂到 Canvas 节点的触摸监听上,而不是在场景加载时就自动播放。这是微信小游戏平台特有的约束。

桥接层建议单独放一个 utils 文件,不要去每个组件里到处写 wx.xxx。原因很简单:编辑器预览、微信开发者工具、浏览器调试,三种环境对 wx 的支持程度不一样,集中的桥接层可以统一处理兼容,出问题也只改一个文件。

5. 小游戏打包避坑:5 个真实踩过的坑和修复

这一章写的是拿到这类源码后最容易踩的坑,每条都是“现象 → 原因 → 解决”的结构,照着排查就行。

5.1 构建后开发者工具报语法错误

现象:构建成功,导入微信开发者工具后,控制台报错指向 game.js 里的箭头函数或 Promise 语法,低版本安卓真机上直接白屏。

原因:构建面板里“ES6 转 ES5”没有勾选。微信基础库在较新版本支持 ES6,但不少安卓手机上的微信版本还没跟上。Creator 默认产物保留 ES6 语法,老环境解析不了。

解决:构建面板里勾选 ES6 转 ES5,重新构建。如果重新构建后仍然报错,检查代码里有没有用 async/await,这种语法不转,需要把相关函数改写成 Promise 链式调用。

5.2 首包体积超过限制

现象:微信开发者工具提示主包大小超限,或者审核被拒,提示“小游戏主包超过 4M”。

原因:素材资源过大。尤其是背景图、音频文件和序列帧图集,没有压缩就直接进了 assets,构建产物把这些资源整包塞进主包。

解决:先看 build/wechatgame/assets 目录里最大的几个文件,确定是哪类资源占空间。图片压缩到合适尺寸,序列帧改成图集(texture atlas),音频转成 AAC 低码率格式。必要时用分包加载功能,把奖励动画、额外关卡的资源放进分包,首包只保留核心玩法资源。

5.3 真机上游戏没有声音

现象:模拟器和 Creator 编辑器里都有声音,真机预览就是安静的。

原因:微信小游戏限制了音频自动播放,必须由用户触摸事件触发播放逻辑。编辑器没有这个限制,所以问题只在真机暴露。

解决:在游戏开始场景加一个“点击开始”按钮,音频播放全部从按钮触摸回调里触发。如果开局前就要有背景音乐,可以在开始按钮的回调里同时启动背景音乐和游戏倒计时,用一次触摸换取整局音频的播放权限。

5.4 全面屏手机画面下方被手势条遮挡

现象:iPhone 或安卓全面屏真机上,游戏底部的地面被系统手势条和 Home 条盖住,UI 按钮点不到。

原因:开发者工具模拟器不模拟全面屏安全区,真机才有这个问题。游戏的设计分辨率适配没有处理 safeArea 区域。

解决:在小游戏适配代码里读取微信的 safeArea 信息,把地面和重要 UI 提升到安全区之内。常见做法是获取 screen.safeArea 的 top 和 bottom 值,换算成设计分辨率坐标,给地面节点和计分 UI 加上偏移。这个工程里因为做了这个适配,真机表现是正常的,如果换到别的工程要记得补上。

5.5 请求远程资源或接口被拦截

现象:排行榜加载失败、远程图片不显示,控制台报错提示“http://xxx 不在以下 request 合法域名列表中”。

原因:微信小游戏的所有网络请求必须走 HTTPS,并且域名必须在微信公众平台配置过合法域名。开发阶段你直接访问公司内网 HTTP 接口,一定被拦截。

解决:开发调试时在微信开发者工具勾选“不校验合法域名”,保证功能能跑;发布前把资源域名和接口域名配置到微信公众平台的后台。注意小游戏的后台配置路径和普通小程序不一样,别搞混了。审核时域名没配置好,功能必然挂了。

6. 二次开发:把“小鸟”骨架改成跑酷或跳跃玩法

最后一章直接给改造思路。这个工程的核心结构是“状态机 + 对象池 + 矩形碰撞”,这套骨架天然适合横向卷轴类玩法,不只限于水管。

6.1 调整手感参数,先定游戏难度曲线

改动手感最快的是调 Bird.ts 和 PipeManager.ts 顶部那几个 @property:

参数当前值效果说明
jumpSpeed-320绝对值调大跳跃幅度变大,调小更“肉”
gravity900调大下落更快,调小腾空时间更长,容错更高
spawnInterval1.5s调小水管节奏变快,游戏进程压力变大
gapHeight220调大容易钻,调小考验操作精度

我一般先调 spawnInterval 和 gapHeight 这对组合,因为它们一个管频率、一个管容错,比单纯调重力对玩家体验的影响更直接。调完跑 10 局,再微调 gravity 让下落的手感顺滑一点。

6.2 把水管换成浮空平台的跳跃玩法

水管对本质是一组移动的“障碍物检查点”。改成平台跳跃,只需要把 PipeManager 生成的预制体从上下两根水管换成一个平台预制体,碰撞逻辑不用改,计分位置从“水管通过后加分”变成“平台通过后加分”。

平台预制体需要加一个 Platform.ts 组件,里面用一个 scored 布尔值记录是否已计分,别的都不变。GameManager 里遍历的仍然是 pipeManager 节点下的子节点,只是碰撞形状从矩形变成了平台自己的包围盒。代码骨架不用动,替换预制体和场景里的节点引用就行。

6.3 给游戏加变速系统

原版始终匀速,玩久了没有压迫感。我建议在 GameManager 里加一个 speedScale 属性,每得 5 分,把 pipeManager 的移动速度整体乘一个系数:

// GameManager.ts 里加一段分数驱动的变速逻辑 onScoreChanged() { const pipeMgr = this.pipeManager.getComponent('PipeManager'); pipeMgr.moveSpeed = 160 + Math.floor(this.score / 5) * 20; }

水管移动速度从初始值开始,每 5 分提高 20,上限可以自己设。这样游戏不会永远停留在同一难度,玩家也有持续挑战的感觉。如果要更平滑,可以把分段改成线性插值,用 score / maxScore 做权重。

改造完记得重新构建一次,在微信开发者工具里跑通完整流程:模拟器预检、真机预览、查看构建体积有没有异常。

说实话,这类工程源码我拆过不少,最大的教训是:改动前一定要先备份构建产物,或者干脆养成每次只改 Creator 源码、重新构建的习惯。直接改 build 目录里的 game.js,重新构建一次之前的修改就全部丢掉,血泪经验。从那以后我每次拿到新工程,第一件事就是确认构建流程能完整跑通,再动代码。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询