easyMenu 开源,让游戏调试更简单!
easyMenu 简介
使用内置的 UI 组件创建一个调试面板通常是一个缓慢而繁琐的过程,为了解决这个问题,二喵开源了自用的调试面板 easyMenu,兼顾了实用性和美观。
这个调试面板支持批量添加菜单组件,就像使用 tween 一样简单。你可以快速添加多个项目,而且维护起来也非常方便。
调试面板内置了一些有用的调试模块,下面我们来了解一下如何使用这些特性和功能, 快速定位游戏的一些性能问题。
FPS 快捷设置
调试面板允许我们手动设置 FPS(每秒帧数),以便测试性能。30 FPS 的开销和发热会更少,但流畅度会有所降低。
const Debug = this.menu.addGroup("Debug");
Debug.addToggle("High FPS", (t) => { game.frameRate = t ? 60 : 30;})
只需要 2 行代码就可以快速添加 FPS 切换,可以点击 Toggle 按钮在 30 FPS 和 60 FPS 间快速切换。
FPS 监控
提到了 FPS 切换,我们再来讲下 FPS 监控,引擎默认只提供了当前 FPS 数值,无法监控 FPS 的变化。
eMenu
提供了 eGraph
图形监控面板,使用简单,可以快速监控如 FPS 变化,场景内敌人数量变换等,下面我们快速设置一下 FPS 监控。
我们首先获取 graph 节点的实例,如下图所示,代表最高数值 60,最多14段数据。
const Debug = this.menu.addGroup("Debug");
Debug.addGraph("FPS", null, 60, 14);
this.graph = Debug.node.getChildByName("FPS").getComponent(eGraph);
然后可以在 update
内统计每秒内的帧数,并推送给 eGraph
面板
time = 0;
counter = 0;
update(dt) {
this.counter += 1;
this.time += dt;
if (this.time >= 1) {
const graph = this.graph;
if (!graph) return;
graph.updateData(this.counter)
this.time -= 1;
graph.NameLable.string = "FPS: " + this.counter;
this.counter = 0;
}
}
我们还可以给 Graph 添加点击事件,通过点击面板,可以获取历史的曲线节点数据。
这些数据也会复制到剪切板,方便粘贴查看。
Overdraw 查看
Overdraw 是指同一个像素点被渲染多次,这通常是由内容冗余、层级混乱或逻辑错误导致的。通过调试面板,我们可以使用代码批量替换精灵的材质,以便更清楚地看到 overdraw 的情况。
testOverdraw() {
this.overdrawMode = !this.overdrawMode;
const children = this.canvasNode.children;
const material: Material = this.overdrawMode ? this.overdrawMat : this.defaultMaterial;
children.forEach((child) => {
if (child == this.menu.node) return;
const sprites = child.getComponentsInChildren(Sprite);
sprites.forEach((sprite) => {
if (!this.defaultMaterial) {
this.defaultMaterial = new Material();
this.defaultMaterial.copy(sprite.material)
}
if (sprite.node.name !== this.node.name) {
sprite.material = material;
}
})
})
}
比如下图的这个 Banner 看起来很正常:
然而这个 Banner 下面隐藏了很多其他精灵:
在实际项目中,这些情况经常发生,脚本逻辑错误,或者忘记删除测试节点都有可能导致 Overdraw,通过点击 Overdraw 按钮,我们可以查看那个像素点有多个精灵图片渲染。
重复渲染的次数越多,红色会越深,针对 Overdraw 的部分,我们可以通过以下方法解决。
- 隐藏背景部分不需要渲染的精灵
- 把大图切割,避免中间大面积的透明像素
养成查看 Overdraw 的习惯,可以降低 GPU 渲染的压力,减轻手机的发热情况。
游戏速度控制
通过重写引擎的 tick
函数,我们可以放慢全局速度,这对动画调试非常有帮助。并且还能用它实现子弹时间、慢动作、加速回放等特殊需求。
@ccclass('TimeScale')
export class TimeScale extends Component {
static scale = 1
start () {
const originalTick = director.tick;
director.tick = (dt: number) => {
dt *= TimeScale.scale;
originalTick.call(director, dt);
}
}
}
这里可以使用调试面板控制全局速度,方便调试动画和特效。
图片内存占用分析
我们可以通过调试面板历遍 assets 中所有的图片资源,并按照尺寸排序,这样就可以找出内存开销最高的图片。结果会自动复制到剪贴板内,方便进一步分析和处理。
getImageMemory(): string {
const assets = assetManager.assets;
let images: ImageAsset[] = [];
assets.forEach((asset) => {
if (asset instanceof ImageAsset) {
images.push(asset);
}
})
images.sort(function (a, b) {
return b.height * b.width - a.height * a.width;
});
let output = "";
let total = 0;
/* get all imagessets mem */
images.forEach((image, i) => {
const self = image;
const native = self._native;
const url = self.url;
const num = Math.floor((self.width * self.height * (native.indexOf('jpg') > 0 ? 3 : 4) / 1024 / 1024) * 10000) / 10000;
total += num;
output = output + "\n" + url + "...." + num + "M";
})
total = Math.floor(total * 10000) / 10000;
output = "Total Image Mem...." + total + "M" + output;
console.log("Image Mem==", output)
this.copyToClipboard(output);
return output;
}
这里会支持打印所有图片的路径和内存占用到剪切板。
我们可以通过路径和图片的 UUID 名字定位到开销高的图片,针对内存占用高的图片可以这么优化。
- JPG 格式由于没有 Alpha 透明通道,内存占用要比 PNG 少 25%,针对背景图片,这里也推荐使用 JPG 格式。
- 针对一些 1920 分辨的大图,可以压缩分辨率到 1280,配合 JPG 使用效果更佳。
- 比较常用的按钮和UI图可以使用九宫格,切除中间区域,来减少图片分辨率。
环境变量设置
在 3D 游戏开发中,有大量的环境变量,我们可以通过 globals
环境变量获取大部分设置。
const scene = director.getScene();
const globals = scene.globals;
const light = scene.getComponentInChildren(DirectionalLight);
const ambientScale = globals.ambient.skyIllum / 100000;
const lightScale = light.illuminance / 100000;
this.menu
.addGroup("Env")
.addToggle("Shadow", (t) => {
globals.shadows.enabled = t;
})
.addToggle("IBL", (t) => {
globals.skybox.useIBL = t;
})
.addToggle("CSM", (t) => {
light.enableCSM = t;
})
.addSlider("Ambient", (p) => {
globals.ambient.skyIllum = p * 100000
}, ambientScale)
.addSlider("Light", (p) => {
light.illuminance = p * 100000
}, lightScale)
通过动态调试这些参数,可以快速定位性能和画面问题。
免费获取源码
此外,easyMenu 也是一个非常有用的工具,可以用于快速添加菜单组件。它内置了按钮, list
, editbox
, slider
, graph
等多种组件,可以点击【阅读原文】免费获取源码。
具体的使用教程可以在商店说明页面查看。
Github 和 Store同步更新,方便的话可以给个 Star:https://github.com/iwae/easyMenu
谢谢大家的支持,二喵会再接再厉,输出更多对大家有用的内容。