开发者问题收集

连续播放 mp3 声音样本时,Phaser 会警告“音频源已存在”

2018-06-14
609

我对加载和播放音效有点困惑。我的游戏设置了不同的状态,首先,预加载器状态确保所有图像和声音都已加载。GameState 是主游戏,此状态在每个下一级别重新启动。有不同的级别,但状态是相同的,它只是更改了 _levelIndex 变量并使用相同的状态。

GameState 在 .create() 函数中将所需的音频添加到游戏中,并且每次启动 GameState 时都会调用此创建函数。请参阅下面的代码

mygame.Preloader.prototype = {
    preload: function(){

        this.loadingbar_bg = this.add.sprite(80, 512, "loadingbar_bg");
        this.loadingbar_fill = this.add.sprite(80, 512, "loadingbar_fill");
        this.load.setPreloadSprite(this.loadingbar_fill);

        // load sounds
        this.load.audio("button", ["snd/button.mp3", "snd/button.ogg"]);
        this.load.audio("punch",  ["snd/punch.mp3",  "snd/punch.ogg"]);
        this.load.audio("coin",   ["snd/coin.mp3",   "snd/coin.ogg"]);
    },
    create: function() {
        this.state.start("MainGame");
    },
};

mygame.GameState.prototype = {

    create: function() {
        this.stage.backgroundColor = "#f0f";
        // etc.

        // sound effects
        this.sound1 = this.game.add.audio("button");
        this.sound2 = this.game.add.audio("punch");
        this.sound3 = this.game.add.audio("coin");
        //etc.
    },

    update: function() {
        if (hitFace) {
            this.sound2.play();
            hitFace = false;
        };
    },

    doNextLevel: function() {
        this.sound1.play();
        this._levelIndex++; // next level
        this.state.start("MainGame"); // restart this state
    },
    //etc.
};

问题是,当我每隔几秒钟连续播放几次打击声音时,控制台会给出此警告(Phaser 在 此处的代码中 引发此警告)

Phaser.Sound: Audio source already exists

即使第一次启动 GameState,也会出现此警告。

我怀疑这与 解码 mp3 和 ogg 声音有关。每次玩家启动(或重新启动)关卡(即重新启动 GameState)时,我是否都必须解码声音样本?换句话说,如果每次关卡(重新)启动时 GameState 都是 .create() ,并且使用 game.add.audio 添加音频样本,那么之前关卡的解码样本是否会被销毁,并且每次都必须重新加载/解码?这似乎很浪费,最好的方法是什么?所以我的问题是:

  1. 此消息“音频源已存在”是什么意思?或者 我应该忽略它吗?
  2. 如果我想在某个状态下使用声音,每次启动状态并调用 .create() 时,我是否必须重新添加它们?
  3. 也有点相关,如果我想在多个不同的状态(菜单、游戏、选项等)中使用相同的声音样本,我是否必须为每个状态的相同声音执行 game.add.audio()
1个回答

嗯,据我所知,您的代码似乎运行正常。所以我将尝试用我所掌握的知识回答您的问题:

1. 此消息“音频源已存在”是什么意思?还是我应该忽略它?

该消息表示,正如您在引发该消息的地方所见,该声音实例已在播放:

if (this._sound && ***!this.allowMultiple***)
    {
        console.warn('Phaser.Sound: Audio source already exists');

        // this._disconnectSource();
    }

如果您尝试播放的声音已由 Phaser.Sound 播放,并且不允许多个播放,则会抛出此错误...这就是问题的根源。 AllowMultiple 来自 源代码

/**
* @property {boolean} allowMultiple - This will allow you to have multiple instances of this Sound playing at once. This is only useful when running under Web Audio, and we recommend you implement a local pooling system to not flood the sound channels.
* @default
*/
this.allowMultiple = false;

所以基本上是在抱怨你试图生成多个不允许多次的声音实例。你不应该忽略它,而是使用正确的标志。

问题 2 和 3:

你不应该重新添加资源,因为这就是你在引擎中加载音频源的原因,以便在所有级别都可以重复使用。您也不必针对所有状态都执行此操作。

为了在多个状态下重用声音,您应该能够在全局范围内添加音频或任何游戏对象并访问它( 在这里我发现有人试图做你在问题中问的事情 ) 其他方法是将这些资源作为属性添加到游戏对象中,这样您就不会污染全局范围,而只会污染游戏对象上下文。 但我相信更好的策略是 在不同状态下添加这些音频 并在状态下管理它们的删除/创建。主要是因为 JS 是邪恶的*并且 可变性可能会对你造成不利影响

*没那么邪恶

要解决此警告:只需使用标志 allowMultiple 在此处创建 ),例如:

    this.sound1 = this.game.add.audio("button") // allowMultiple is false by default
    this.sound2 = this.game.add.audio("punch");
    // Allow multiple instances running at the same time for sound2
    this.sound2.allowMultiple = true;
    this.sound3 = this.game.add.audio("coin");
    // Allow multiple instances running at the same time for sound3
    this.sound3.allowMultiple = true;
SirPeople
2018-06-21