发牢骚
最近在做一款物理小游戏的时候,在大量物体碰撞的时候,出现了游戏卡顿,甚至帧数降到10以下,直接卡住很久的情况。
cocoscreator的物理引擎性能经常被开发者诟病,由于短时间了,200-300个刚体发生碰撞,数量有点多,我一度怀疑是物理引擎的锅,找着找着,原来是频繁调用play音效的问题。几百个刚体碰撞,就会调用几百次的play方法来播放碰撞音效,这才是根本原因。
相信你也很快就能找到解决
方法1
既然一次性调用太多次play导致卡,那就分帧播放,分担每一帧的压力 实现如下:
//声明回调方法
export type CallbackVoid = () => void;
...
//创建播放音效的回调函数列表
private willPlayEffects: CallbackVoid[] = [];
...
/**
* 在碰撞的时候,将播放声音的回调压入到列表李里面
*/
protected beginContact(contact: cc.PhysicsContact, selfCollider: cc.PhysicsCollider, otherCollider: cc.PhysicsCollider): void {
if (otherCollider.node.group === "Column"){
const fun: CallbackVoid = () => {
AudioPlayer.playEffectCache(ResPath.Sound.Collision);
}
this.willPlayEffects.push(fun);
}
}
...
protected update(dt: number){
if (this.willPlayEffects.length === 0) return;
const fun = this.willPlayEffects.shift();
fun();
}
//如果音效太多,可以一帧多播放几个,比如播放10个,否则你会发现,声音会让你产生如蚊子飞到你耳朵附近的那种难受的感觉
protected update(dt: number){
for (let i = 0; i < 10; i++) {
if (this.willPlayEffects.length === 0) return;
const fun = this.willPlayEffects.shift();
fun();
}
}
复制代码
方法2
可以将短时间重复播放的音效合成一个,来循环播放,或者直接单音循环播放也可以起到优化的效果。在碰撞或者动画结束的时候,暂停(pause)音效播放即可,下次只要resume 就好。或者可以设置在几秒之内重复收到同样的音效不执行。
总之就是避免频繁的 执行 play。