1

我正在用 libgdx 构建一个滚动射击游戏。在 Windows 中,一切运行良好,但在 android 上我得到明显的抖动,帧率从 61 fps avg 没有声音下降到 48-56 fps avg 有声音。它同时播放许多小音效,因为有很多子弹要发射,敌人要同时击中。我的声音例程:

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;

public class SoundFX {

    static final int BGDIE = 1, BGHIT = 2, BGLASER = 3, BGSPAWN = 4, PDIE = 5, PHIT = 6, PLASER = 7, PSPAWN = 8, PAUSE = 9;
    Sound S_BGDIE, S_BGHIT, S_BGLASER, S_BGSPAWN, S_PDIE, S_PHIT, S_PLASER, S_PSPAWN, S_PAUSE;

    public void load()
    {
        S_BGDIE = Gdx.audio.newSound(Gdx.files.internal("data/sfx/badguydie.mp3"));
        S_BGHIT = Gdx.audio.newSound(Gdx.files.internal("data/sfx/badguygothit.mp3"));
        S_BGLASER = Gdx.audio.newSound(Gdx.files.internal("data/sfx/badguylaser.mp3"));
        S_BGSPAWN = Gdx.audio.newSound(Gdx.files.internal("data/sfx/badguyspawn.mp3"));
        S_PDIE = Gdx.audio.newSound(Gdx.files.internal("data/sfx/playerdie.mp3"));
        S_PHIT = Gdx.audio.newSound(Gdx.files.internal("data/sfx/playergothit.mp3"));
        S_PLASER = Gdx.audio.newSound(Gdx.files.internal("data/sfx/playerlaser.mp3"));
        S_PSPAWN = Gdx.audio.newSound(Gdx.files.internal("data/sfx/playerspawn.mp3"));
        S_PAUSE = Gdx.audio.newSound(Gdx.files.internal("data/sfx/pause.mp3"));
    }

    public void unload()
    {
        S_BGDIE.dispose();
        S_BGHIT.dispose();
        S_BGLASER.dispose();
        S_BGSPAWN.dispose();
        S_PDIE.dispose();
        S_PHIT.dispose();
        S_PLASER.dispose();
        S_PSPAWN.dispose();
        S_PAUSE.dispose();
    }

    public void play(int id)
    {
        switch(id)
        {
        case BGDIE:
            S_BGDIE.play();
            break;
        case BGHIT:
            S_BGHIT.play();
            break;
        case BGLASER:
            S_BGLASER.play();
            break;
        case BGSPAWN:
            S_BGSPAWN.play();
            break;
        case PDIE:
            S_PDIE.play();
            break;
        case PHIT:
            S_PHIT.play();
            break;
        case PLASER:
            S_PLASER.play();
            break;
        case PSPAWN:
            S_PSPAWN.play();
            break;
        case PAUSE:
            S_PAUSE.play();
            break;
        default:
            System.out.println("invalid sfx call");
            break;
        }
    }
}

根据游戏中发生的情况,play 大约每秒调用 4-10 次,声音效果的持续时间不到一秒,平均每个 8kb。

这是怎么回事,我该如何解决这个问题?它使游戏看起来非常不专业,并且在困难的水平上几乎无法玩。

4

2 回答 2

5

关于为什么在播放多个声音时会注意到性能大幅下降的问题的一些背景知识。这是因为在幕后 libgdx 需要在将声音播放回用户之前将它们混合在一起。当您同时运行一定数量的声音时,对系统进行混音的要求会变得非常高。由于您可能会在渲染线程上尝试播放声音,因此需求的增加会导致帧率下降。

根据我对游戏中任何类型音效的经验,当您遇到同时播放大量小声音的情况时,几乎没有解决方案。我将把这些写成比 libGDX 的细节更通用的解决方案:

1)在一个线程上播放所有声音

这就是您当前正在做的事情,虽然它在播放大量声音时效果不佳,但它很容易实现并且在大多数情况下都有效。然而,一旦你得到足够多的声音一起播放,你会注意到延迟和质量差。

2)在与渲染线程不同的线程上播放声音

这是一种可能的方法(取决于框架是否允许),它不是很好,因为它不能很好地扩展。但是,如果您只是遭受轻微的性能损失并且不希望同时播放大量(~20+)声音,这是一个相对较小的更改,通常可以解决问题。

3)播放声音达到上限

此解决方案需要更多工作,如果您有必须播放的声音,则可能无法接受。您只需跟踪播放的声音数量并允许播放其他声音,直到您达到某个点。任何超过上限的内容都不会播放。这使您可以保证一定的性能水平。这种方法的最大缺点是,如果你在角色受重伤并且没有播放时播放声音,那么这可能会让用户感到不安,因为他们可能正在听声音以知道他们是否会很快死去,反而发现自己死了。

4)有选择地播放重要的声音

这有点难以实现,但它的效果非常好,因为您实际上是在设置性能上限。您要做的是确定播放声音的优先级。它离你很近吗?声音大吗?那很重要么?然后,您只播放重要到足以播放到某个上限(可能是 4、6、8 等)的声音。您还需要跟踪当前播放的声音数量,以确定在给定点可以播放多少新声音。

于 2013-04-01T17:21:20.340 回答
0

一种解决方法:播放对玩家来说不太重要的声音,只有在当前 FPS 高于某个值时才能播放它们。例如:

if (Gdx.graphics.getFramesPerSecond() > 56) playSound();

无论 FPS 值如何,都应始终播放重要的声音。

于 2017-10-17T12:40:43.843 回答