前两篇写了环境搭建、后台管理和服务端逻辑,这一篇就是收官之作:前端UI重构、性能优化、模块拆分、以及深度二开的一些小技巧。这一部分才是最费心思的地方,也是我反复调试最多的环节。
刚拿到源码时,前端 UI 虽然能用,但风格参差不齐。大厅界面是一套配色,子模块又是另一套,按钮和弹窗有时候还闪屏。看着就像临时拼出来的 demo。要让它真的“好用”,必须先梳理资源、优化加载,再考虑二开。
一、UI重构:从“能跑”到“看着顺眼”
我的第一步是把 assets/resources
下的图片重新分类,把常用的颜色、字体、间距写在一个全局样式文件里,Prefab 统一管理。这样改一次全局生效。
例如我在 style.js
定义:
export const Theme = {
primaryColor: cc.color(255, 215, 0),
fontFamily: 'Arial',
buttonRadius: 8,
titleSize: 30
};
Prefab 挂载脚本里这样读:
this.node.color = Theme.primaryColor;
this.node.getComponent(cc.Label).fontFamily = Theme.fontFamily;
this.node.getComponent(cc.Label).fontSize = Theme.titleSize;
这比一堆地方手动改舒服太多。
二、性能优化:不卡顿才是真的优化
cocosCreator 的场景如果节点太多,很容易在手机上卡顿。我用的几招:
- 按需加载:不要一上来全加载所有子模块,用
cc.assetManager.loadBundle
分包加载:
cc.assetManager.loadBundle('moduleA', (err, bundle) => {
if (!err) {
bundle.loadScene('moduleA', (err, scene) => {
cc.director.runScene(scene);
});
}
});
- 对象池:频繁出现的节点(比如列表项、子弹、特效)都放进对象池:
const nodePool = new cc.NodePool();
function getNode(prefab) {
return nodePool.size() > 0 ? nodePool.get() : cc.instantiate(prefab);
}
function putNode(node) {
nodePool.put(node);
}
这样内存占用立刻降低。
- 压缩资源:把PNG改成WebP,音频改成Ogg。Cocos官方工具能一键压缩,省下近一半空间。
- 帧率监控:开发时右上角加 FPS 显示:
cc.director.setDisplayStats(true);
这样能直观地看到掉帧的位置,方便优化。
三、模块拆分:把“一锅炖”变成“分层走”
原始源码的很多逻辑都写在一起,大厅和子模块耦合很紧。我做了模块拆分:
- 公共逻辑(登录、接口请求、全局数据)抽到
common
模块 - 每个子模块单独放
modules
文件夹 - 用事件总线做模块间通信
事件总线示例:
const EventBus = new cc.EventTarget();
// 监听
EventBus.on('update-score', data => {
console.log('Score updated', data);
});
// 触发
EventBus.emit('update-score', {score: 200});
大厅只管发事件,子模块自己监听。耦合降到最低,后期维护和二开都轻松。
四、深度二开小技巧
1. 动态模块配置
我在后台加了一张配置表,控制哪些模块加载。前端启动时拉一次:
axios.get('/api/module/config').then(res => {
res.data.forEach(m => {
if (m.enabled) loadModule(m.name);
});
});
想关哪个模块只改配置,不用动前端代码。
2. 多资源包管理
用 Asset Bundle 把常用模块打包,冷门模块单独打包。这样更新冷门模块时不用全量更新app。
3. 热更新
Cocos官方热更新插件很好用,改几行就能上线。对于多模块系统这是救命稻草。
4. 日志收集
前端写个 window.onerror
钩子把错误上报到后端:
window.onerror = function (msg, url, line, col, error) {
fetch('/api/logs', {
method: 'POST',
body: JSON.stringify({ msg, url, line, col })
});
};
这样能第一时间看到线上报错。
5. 统一接口响应格式
后端统一返回 {code, msg, data}
,前端统一处理:
function sendRes(res, data, code = 0, msg = 'ok') {
res.json({ code, msg, data });
}
不用每个接口单独判断。
五、版本管理和协作
源码这么大,必须用Git管理。我的做法:
- main:稳定版
- dev:开发版
- feature/xxx:新功能
- fix/xxx:修bug
每次改动提交一次,写清commit说明。出了问题能立刻回滚。
六、我的UI坑总结
- 不要把所有按钮事件都绑在一个JS里,拆开写,维护方便
- 不要在Prefab里硬写路径,用全局函数
- 大图切小图,用Atlas打包
- 不要在Update里写一堆逻辑,CPU吃不消
七、从“能跑”到“真香”
做完这些优化,整个项目的体验完全不一样。子模块加载速度从几秒变成一秒以内,UI主题统一、维护成本大幅下降。
很多人拿到源码就直接改业务逻辑,其实真正省时间的做法是先把架构、UI和性能打磨好,再做功能迭代。这样后面二开才不会踩坑。
这一篇写完,三部曲也就告一段落了。从搭建到后台,从服务端到前端,从踩坑到优化,这套源码被我“拆干净”之后,已经完全成了可以自由发挥的框架。希望这些手记对你们有帮助。
转载请注明出处,仅限技术交流,禁止商用。
相关文章:
下载地址: