Discord.net:用户首次连接语音频道时UserVoiceStateUpdated事件未触发
解决UserVoiceStateUpdated事件不触发首次连接/重连的问题
这问题我太熟了!很多人刚用语音状态事件的时候都会踩这个坑——本质是UserVoiceStateUpdated的触发逻辑和你预期的不一样:它默认只在用户已有语音状态的前提下发生变更(也就是切换频道)才会触发,而首次连接(从无到有)、断开后重连(从断开到连接)这两种场景,因为没有「旧状态」或者旧状态是“无连接”,部分库的事件实现就不会触发它。
下面给你几个靠谱的解决思路:
1. 切换到更全面的语音状态事件
大部分Discord开发库(比如Discord.js、Discord.NET)都提供了覆盖所有语音状态变化的底层事件,比如Discord.js里的voiceStateUpdate,它会在所有语音状态变更时触发——包括首次连接、重连、切换频道、断开连接。
你只需要把监听的事件换成这个,然后在逻辑里区分不同的状态变化场景就行,比如:
// Discord.js 示例代码 client.on('voiceStateUpdate', (oldState, newState) => { // 捕获首次连接/断开重连:旧状态无频道,新状态有频道 if (!oldState.channel && newState.channel) { console.log(`${newState.member.user.tag} 加入了语音频道 ${newState.channel.name}`); // 这里写你的响应逻辑,比如发送欢迎消息、执行特定指令等 } // 捕获频道切换:新旧状态都有频道且不同 if (oldState.channel && newState.channel && oldState.channel.id !== newState.channel.id) { console.log(`${newState.member.user.tag} 切换到了 ${newState.channel.name}`); } // 捕获断开连接:旧状态有频道,新状态无频道 if (oldState.channel && !newState.channel) { console.log(`${newState.member.user.tag} 离开了语音频道`); } });
2. 补充初始化状态检查+手动跟踪
如果因为某些原因你必须用UserVoiceStateUpdated,那可以做两步补充:
- 机器人启动时,遍历所有服务器的语音频道,把当前已经在频道里的成员记录下来,并且手动执行一次你的响应逻辑(相当于处理“机器人启动前就已经在频道的成员”的情况)。
- 每次用户断开语音时,更新你的状态记录为“断开”,这样当他们重连时,事件会因为状态从“断开”变为“连接”而触发(前提是库支持这种状态对比)。
3. 检查并升级你的库版本
有些旧版本的Discord库确实存在这个bug——没有把“从无到有”的语音状态变化纳入UserVoiceStateUpdated的触发范围。去看看你用的库的最新版本,很多这类问题在新版本里已经被修复了。
内容的提问来源于stack exchange,提问作者Georg Z.
相关产品推荐
相关产品推荐

