ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Phaser 3.60.0 音频系统深度解析:Sound Manager 新特性、自动恢复机制与兼容性修复

Phaser 3.60.0 音频系统深度解析:Sound Manager 新特性、自动恢复机制与兼容性修复 Phaser 3.60.0 音频系统深度解析Sound Manager 新特性、自动恢复机制与兼容性修复【免费下载链接】phaserPhaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.项目地址: https://gitcode.com/gh_mirrors/ph/phaser本文聚焦 Phaser 3.60.0 版本对 Sound Manager声音管理器的一次系统性升级涵盖新增的gameLostFocus状态追踪、getAllPlaying批量查询方法、Web Audio 上下文自动恢复机制、Device.Audio能力检测模块重写以及 NoAudio 回退管理器的完整补齐。读完本文你将理解这些改动背后的实现原理、对应的源码位置以及如何在新版本中正确使用这些 API 来构建跨设备、抗中断的健壮音频系统。本文内容基于 changelog/v3/3.60/Sound.md 中的变更记录并对照仓库源码逐一印证。一、版本背景一次以稳定性为核心的音频升级Phaser 3.60.0 的 Sound Manager 改动没有引入颠覆性的新玩法而是围绕三个核心目标展开更可靠的失焦/恢复处理、更强的音频能力探测、更完整的 API 一致性。从变更条目来看绝大多数改动都直接指向移动端 Safari、Android 13 等真实场景下的音频中断问题——这些正是 H5 游戏音频最棘手的痛点。在深入新特性之前先明确 Sound Manager 的三套实现源码位于 src/sound/实现类源码路径适用场景WebAudioSoundManagersrc/sound/webaudio/WebAudioSoundManager.js设备支持 Web Audio API 时的默认实现HTML5AudioSoundManagersrc/sound/html5/HTML5AudioSoundManager.jsWeb Audio 不可用时的降级实现NoAudioSoundManagersrc/sound/noaudio/NoAudioSoundManager.js设备完全不支持音频或游戏配置中显式禁用音频时的空实现三者共享 src/sound/BaseSoundManager.js 这个基类本次 3.60.0 的大多数新增特性都落在基类上从而让三套实现同步受益。二、新特性gameLostFocus与getAllPlaying1.BaseSoundManager.gameLostFocus可靠追踪游戏焦点变更记录BaseSoundManager.gameLostFocus是一个新的布尔属性当游戏失去焦点时为true重新获得焦点时为false。该属性在基类构造函数中初始化见 src/sound/BaseSoundManager.js/** * Flag used to track if the game has lost focus. * name Phaser.Sound.BaseSoundManager#gameLostFocus * type {boolean} * default false * since 3.60.0 */ this.gameLostFocus false;关键在于它由基类统一挂接的两个内部事件处理器来维护src/sound/BaseSoundManager.jsonGameBlur: function () { this.gameLostFocus true; if (this.pauseOnBlur) { this.onBlur(); } }, onGameFocus: function () { this.gameLostFocus false; if (this.pauseOnBlur) { this.onFocus(); } }这两个处理器在构造函数中分别订阅了Phaser.Core.Events.BLUR与Phaser.Core.Events.FOCUS游戏级事件。从源码结构可以推断gameLostFocus的引入价值在于它把游戏是否失焦这一状态从是否执行暂停动作中解耦出来——即使pauseOnBlur为false不主动暂停你也依然可以通过this.sound.gameLostFocus感知到焦点状态为自定义的降级策略如降低音量、停止密集音效提供依据。2.BaseSoundManager.getAllPlaying一键获取所有正在播放的声音变更记录BaseSoundManager.getAllPlaying是一个新方法返回 Sound Manager 中所有当前正在播放的声音。实现非常简洁src/sound/BaseSoundManager.js本质是对sounds数组按isPlaying true过滤getAllPlaying: function () { return GetAll(this.sounds, isPlaying, true); }它复用了工具函数GetAll来自 src/utils/array/GetAll.js。典型使用场景// 在 Scene 中停止所有正在播放的音效 const playing this.sound.getAllPlaying(); playing.forEach(sound sound.stop());配合原有的getAll(key)现在可以同时实现按 key 查与按播放状态查两种批量维度在管理大量战斗音效、UI 音效时非常实用。三、更新从能力探测到自动恢复1. 无匹配音频 URL 时输出控制台警告变更记录如果没有 Audio URL 能匹配当前设备现在会在控制台显示一条警告感谢 samme。该逻辑位于音频加载器的工厂函数 src/loader/filetypes/AudioFile.jsvar urlConfig AudioFile.getAudioURL(game, urls); if (!urlConfig) { console.warn(No audio URLs for %s can play on this device, key); return null; }底层探测函数getAudioURL会遍历你提供的 URL 列表逐个用game.device.audio[audioType]检查当前设备是否支持对应格式src/loader/filetypes/AudioFile.js其中blob:与data:开头的 URI 会被无条件接受。当所有格式都不支持时加载器不再静默失败而是直接提示你该设备没有任何一个备选格式能播。这提醒开发者在配置音频加载时尽量提供多格式回退列表this.load.audio(title, [ music/Title.ogg, music/Title.mp3, music/Title.m4a ]);2.getAll方法的key参数改为可选变更记录BaseSoundManager.getAll过去必须传入key参数才能返回匹配的声音现在该参数可选不传则返回全部 Sound 实例。实现见 src/sound/BaseSoundManager.jsgetAll: function (key) { if (key) { return GetAll(this.sounds, key, key); } else { return GetAll(this.sounds); } }两种调用方式均合法const allSounds this.sound.getAll(); // 全部声音 const bgmOnly this.sound.getAll(background); // 仅 key 为 background 的声音3. Web Audio 上下文进入suspended/interrupted时自动恢复修复 #5353变更记录WebAudioSoundManager现在会在其更新循环中检测 Audio Context 是否进入suspended或interrupted状态如果是则尝试恢复。这常见于以下场景更换/禁用音频设备例如插入带音频驱动的耳机后又拔掉、在 iOS 上切换标签页等。这是本次更新中技术上最值得关注的一条。核心实现在 src/sound/webaudio/WebAudioSoundManager.js 的onFocus方法onFocus: function () { var context this.context; if (context !this.locked (context.state suspended || context.state interrupted)) { context.resume(); } }而onFocus的调用时机从基类的仅在焦点事件触发时调用一次升级为在update循环中每帧检测src/sound/webaudio/WebAudioSoundManager.jsBaseSoundManager.prototype.update.call(this, time, delta); // Resume interrupted audio on iOS only if the game has focus if (!this.gameLostFocus) { this.onFocus(); }这段代码与新增的gameLostFocus属性形成了漂亮的配合每帧都会检查 AudioContext 的状态只要游戏保持焦点、上下文处于suspended/interrupted就尝试resume()。这修复了拔插音频设备、iOS 切换标签页后音频静默卡死的问题。对开发者而言这意味着大多数音频中断场景现在可以无需任何业务代码即可自愈。4.Device.Audio模块重写CanPlay函数与 aac/flac 支持变更记录Device.Audio模块被重写使用新的内部CanPlay函数大幅精简了代码量Device.Audio.aac是新布尔属性表示浏览器能否播放 aac 音频文件使其可通过 Loader 加载感谢 Ariorh1337Device.Audio.flac是新布尔属性表示浏览器能否播放 flac 音频文件使其可通过 Loader 加载感谢 Ariorh1337。重写后的 src/device/Audio.js 将此前针对每种格式的重复探测逻辑收敛为一个内部CanPlay辅助函数var CanPlay function (type1, type2) { var canPlayType1 audioElement.canPlayType(audio/ type1).replace(/^no$/, ); if (type2) { return Boolean(canPlayType1 || audioElement.canPlayType(audio/ type2).replace(/^no$/, )); } else { return Boolean(canPlayType1); } }; Audio.ogg CanPlay(ogg; codecsvorbis); Audio.opus CanPlay(ogg; codecsopus, opus); Audio.mp3 CanPlay(mpeg); Audio.wav CanPlay(wav); Audio.m4a CanPlay(x-m4a); Audio.aac CanPlay(aac); Audio.flac CanPlay(flac, x-flac); Audio.webm CanPlay(webm; codecsvorbis);注意flac探测时同时尝试了audio/flac与audio/x-flac两种 MIME 类型以覆盖不同浏览器的实现差异。完整的属性清单定义在 src/device/Audio.js包括audioData、dolby、m4a、mp3、ogg、opus、wav、webAudio、webm以及新增的aac、flac。这套能力探测结果在游戏启动阶段填充你可以在任意 Scene 中通过this.sys.game.device.audio访问。新增的aac/flac属性直接打通了 Loader 对这两种格式的支持链路——getAudioURL会依据这些属性自动挑选可播放的 URL。这意味着你现在可以放心地在加载配置中把.aac、.flac文件加入回退列表this.load.audio(theme, [ theme.flac, theme.ogg, theme.mp3 ]);5.NoAudioSoundManager补齐全部缺失方法变更记录NoAudioSoundManager现在拥有了全部缺失的方法例如removeAll和get使其可以作为 HTML5 与 Web Audio Sound Manager 的直接替代品感谢 orjandh samme。此前无音频模式下的管理器只保留了最基本的方法任何在无音频设备上运行的代码只要调用了removeAll等方法就会直接报错。3.60.0 在 src/sound/noaudio/NoAudioSoundManager.js 中补齐了接口其中相当一部分直接委托给基类实现例如get: function (key) { return BaseSoundManager.prototype.get.call(this, key); }, removeAll: function () { return BaseSoundManager.prototype.removeAll.call(this); }, removeByKey: function (key) { return BaseSoundManager.prototype.removeByKey.call(this, key); }而play、playAudioSprite则保持始终返回false的语义其余pauseAll、resumeAll、stopAll、update、unlock等方法统一使用NOOP空操作占位见 src/sound/noaudio/NoAudioSoundManager.js注释中明确说明这是为了与其他 Sound Manager 保持兼容。这种设计让业务代码在无音频设备上可以无差别运行——调用存在、返回安全值、绝不抛错体现了 Phaser 在优雅降级上的工程态度。四、Bug 修复三个真实场景的根因剖析1.pauseOnBlur在部分浏览器上失效修复 #6354变更记录在部分浏览器如 Android 13 上的 Firefox 与 Chrome中游戏失焦时设置SoundManager.pauseOnBlur true无法停止音频。现在通过新的gameLostFocus标志强制执行。感谢 klaritan 与 michalfialadev。该问题的根因在于某些浏览器在标签页后台化后blur事件可能不被可靠派发或派发时机过晚。3.60.0 中gameLostFocus作为独立的状态标志被维护并配合WebAudioSoundManager.update中每帧仅当!this.gameLostFocus时才执行onFocus()的守卫src/sound/webaudio/WebAudioSoundManager.js从事件驱动转向事件 状态驱动双重保障。2. WebAudioSound 销毁时的节点重复断开错误变更记录在同一个游戏步内同时销毁WebAudioSound与 Game 本身会在尝试断开已断开的 Web Audio 节点时报错。WebAudioSound现在会在销毁序列开始前检查是否已处于待移除状态。对应的守卫逻辑在 src/sound/webaudio/WebAudioSound.jsdestroy: function () { if (this.pendingRemove) { return; } BaseSound.prototype.destroy.call(this); // ... 随后断开 muteNode / volumeNode / pannerNode / spatialNode }pendingRemove标志在基类 src/sound/BaseSound.js 的destroy中被置为true。同时基类的update循环会每帧清理带有pendingRemove标记的声音src/sound/BaseSoundManager.js形成标记 → 清理的安全生命周期。这一修复对频繁切换场景、动态销毁大量音频对象的游戏尤为重要。3. iOS 14 Safari 音频解锁回归修复 #5696变更记录iOS 14 及以上版本的 Safari 中音频现在可以正确解锁了。感谢 laineus。iOS 的 Web Audio 自动播放策略一直是最复杂的兼容性问题之一。结合上文提到的interrupted状态检测该状态正是 iOS 上音频被系统打断时的典型表现可以推断此次修复的核心思路是在update循环中持续检测context.state一旦发现interrupted/suspended且游戏持有焦点便主动调用context.resume()从而绕开此前必须在用户手势中解锁的单点失效问题。配合gameLostFocus标志即使页面在 Safari 中被切到后台再切回也能在聚焦后第一时间恢复音频。五、总结如何把这批改动用起来将本次 3.60.0 的改动落地的推荐做法升级后无需迁移代码——getAll、getAllPlaying、gameLostFocus均为纯增量 API旧代码完全兼容利用gameLostFocus实现自定义降级例如失焦时降低音量而非彻底静音this.sound.on(gameblur, () { /* 自定义处理 */ }); // 或直接读取 this.sound.gameLostFocus在音频资源列表中混入 aac/flac 格式让 Loader 自动为支持的设备挑选更优格式信任自动恢复机制suspended/interrupted状态的检测与恢复已内置无需再手写context.resume()的轮询逻辑。本次变更的完整对照源码均可追溯基类行为见 src/sound/BaseSoundManager.jsWeb Audio 实现见 src/sound/webaudio/WebAudioSoundManager.js 与 src/sound/webaudio/WebAudioSound.js能力探测见 src/device/Audio.js加载警告见 src/loader/filetypes/AudioFile.js。相关单元测试覆盖了基类行为tests/sound/BaseSoundManager.test.js与无音频模式tests/sound/noaudio/NoAudioSoundManager.test.js可作为进一步研读的入口。回到 变更日志索引 可查看同一版本其他模块的更新。【免费下载链接】phaserPhaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.项目地址: https://gitcode.com/gh_mirrors/ph/phaser创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表