描述问题
std::vector<sf::Sound> 中存储的音效在播放过程中会意外中断。
- 在
play() 中将开始播放的 sf::Sound 放入容器,运行时却没有声音
- 单个 SE 播放正常,但连续播放多个 SE 时全部意外中断。
- 当有其他音效播放完毕被清理时,正在播放的长音效会被提前停止。
例如:播放一个 7 秒的走路声,在另一个短音效(0 秒)播放完毕后,走路声随即中断,实际只播放了约 0.7 秒。
复现步骤
场景1. 不采用直接在容器内构造的 emplace_back()
场景2. 在脚本中构建连续多个播放 SE 的指令
场景3. 在通道构造函数中预先分配好容器的容量,同时播放长短不一的多个 SE
预期行为
所有 SE 应该完整播放,互不干扰。
实际行为
各场景处于播放中的 SE 被提前中断。
以场景3为例,7秒的 se_walk 实际只播放了约 0.7 秒。
[14:25:40.029] debug [endeus] SEChannel.cpp :21 | SE played: se_ok
[14:25:40.029] debug [endeus] GloriousDays.cpp :23 | get audio asset type: 4 by alias: se_walk
[14:25:40.030] debug [endeus] ResourceCache.hpp :30 | loadResource: path=assets/audio/se/se_walk.ogg, cached=false
[14:25:40.102] debug [endeus] ResourceCache.hpp :38 | loadResource: path=assets/audio/se/se_walk.ogg, success=true
[14:25:40.103] debug [endeus] SEChannel.cpp :21 | SE played: se_walk
[14:25:40.104] debug [endeus] GloriousDays.cpp :23 | get audio asset type: 4 by alias: se_door_open
[14:25:40.104] debug [endeus] ResourceCache.hpp :30 | loadResource: path=assets/audio/se/se_door_open.ogg, cached=false
[14:25:40.126] debug [endeus] ResourceCache.hpp :38 | loadResource: path=assets/audio/se/se_door_open.ogg, success=true
[14:25:40.126] debug [endeus] SEChannel.cpp :21 | SE played: se_door_open
[14:25:40.127] debug [endeus] Executor.cpp :92 | FadeLayer: id='door', from alpha 0.8 to 0, duration=1s
[14:25:40.127] debug [endeus] Executor.cpp :49 | ShowLayer: id='ev_reader', texture='ev_reader', pos=(0,0), alpha=0, order=0
[14:25:40.128] debug [endeus] WorldManager.cpp :14 | addLayer: id='ev_reader', texture='ev_reader', order=0, pos=(0,0), alpha=0
[14:25:40.128] debug [endeus] Executor.cpp :92 | FadeLayer: id='ev_reader', from alpha 0 to 1, duration=1s
[14:25:40.128] debug [endeus] Executor.cpp :122 | SetContent: append=false, text='你选择了...'
[14:25:40.129] debug [endeus] WorldManager.cpp :87 | setContent: replace mode
[14:25:40.129] debug [endeus] ResourceCache.hpp :30 | loadResource: path=assets/images/ev/ev_reader.png, cached=false
[14:25:40.214] debug [endeus] ResourceCache.hpp :38 | loadResource: path=assets/images/ev/ev_reader.png, success=true
[14:25:40.234] debug [endeus] Anemoi.cpp :24 | Anemoi update: 1 animation(s) completed
[14:25:40.846] debug [endeus] SEChannel.cpp :41 | update: 1 SE(s) completed
[14:25:41.015] debug [endeus] BGMChannel.cpp :78 | fade out completed, BGM stopped
[14:25:41.016] debug [endeus] Anemoi.cpp :24 | Anemoi update: 2 animation(s) completed
[14:25:41.134] debug [endeus] Anemoi.cpp :24 | Anemoi update: 1 animation(s) completed
[14:25:41.303] debug [endeus] SEChannel.cpp :41 | update: 1 SE(s) completed
[14:25:41.320] debug [endeus] SEChannel.cpp :41 | update: 1 SE(s) completed
根因分析
- SFML 源码中
sf::Sound::setBuffer() 会先调用 stop()。
sf::Sound 的拷贝构造/拷贝赋值/析构都会触发停止。
std::vector 扩容时的重新分配或移除元素的 erase_if 时,元素被拷贝/销毁,导致正在播放的声音中断。
解决方案
已改用 std::array<std::unique_ptr<sf::Sound>, MAX_SE>,避免任何拷贝。
环境
- 操作系统:Windows 11
- 引擎版本:0.5.0
- SFML 版本:3.0.2
描述问题
std::vector<sf::Sound>中存储的音效在播放过程中会意外中断。play()中将开始播放的sf::Sound放入容器,运行时却没有声音例如:播放一个 7 秒的走路声,在另一个短音效(0 秒)播放完毕后,走路声随即中断,实际只播放了约 0.7 秒。
复现步骤
场景1. 不采用直接在容器内构造的
emplace_back()场景2. 在脚本中构建连续多个播放 SE 的指令
场景3. 在通道构造函数中预先分配好容器的容量,同时播放长短不一的多个 SE
预期行为
所有 SE 应该完整播放,互不干扰。
实际行为
各场景处于播放中的 SE 被提前中断。
以场景3为例,7秒的
se_walk实际只播放了约 0.7 秒。根因分析
sf::Sound::setBuffer()会先调用stop()。sf::Sound的拷贝构造/拷贝赋值/析构都会触发停止。std::vector扩容时的重新分配或移除元素的erase_if时,元素被拷贝/销毁,导致正在播放的声音中断。解决方案
已改用
std::array<std::unique_ptr<sf::Sound>, MAX_SE>,避免任何拷贝。环境