Roblox触摸触发音效重复播放致Studio崩溃问题求助
Roblox Lua语音触发脚本异常排查与修复
预期功能
- 为
Positions文件夹内每个Position对象克隆父级Sound并播放 - 同步在游戏内屏幕显示字幕序列
完整脚本(原始版本)
local Players = game:GetService("Players"); local RunService = game:GetService("RunService"); local col = script.Parent:WaitForChild("Collision", 30); local audioPositions = script.Parent:WaitForChild("Positions"):GetChildren(); local voiceline = script.Parent; local subtitleSequence = script.Parent:WaitForChild("SubtitleSequence"):GetChildren(); --[[Contains a function that creates an audio clone by passing the audio to clone and a target parent which is used on this script (and as far as I know, it works)]] local audioFunc = require(game:GetService("ReplicatedStorage").__AUDIO); --[[Used to return the GameGui Subtitles text used to play out the subtitle sequence (again, as far as I know, it works)]] local gameUIFunc = require(game:GetService("ReplicatedStorage").__GAME_UI); local touched = false; local function RunSubtitleSequence() for i, subtitle in pairs(subtitleSequence) do local duration = subtitle:WaitForChild("Duration"); local subtitleText = gameUIFunc.returnSubtitlesTextObject(Players.LocalPlayer); if subtitleText == nil then return; end; subtitleText.Text = subtitle.Value; wait(duration.Value); end; gameUIFunc.returnSubtitlesTextObject(Players.LocalPlayer).Text = ""; end; col.Touched:Connect(function() RunService.Heartbeat:Wait(); if touched then return; end; touched = true; RunService.Heartbeat:Wait(); for i, audioPosition in pairs(audioPositions) do audioFunc.createSound(voiceline, audioPosition); end; RunService.Heartbeat:Wait(); task.spawn(function() RunSubtitleSequence(); end); end);
对象结构
|----Sound [SOUND] |----|----Positions [FOLDER] |----|----|----Position [PART] |----|----|----Position [PART] |----|----|----Position [PART] |----|----SubtitleSequence [FOLDER] |----|----|----0 [STRINGVALUE] |----|----|----|----Duration [INTVALUE] |----|----|----1 [STRINGVALUE] |----|----|----|----Duration [INTVALUE] |----|----VoicelineTrigger [LOCALSCRIPT] |----|----Collision [PART]
已尝试手段
- 添加
touched防抖标记 - 插入
RunService.Heartbeat:Wait()做帧同步 - 使用
task.spawn()异步执行字幕序列 - 改用
:Once()绑定事件并销毁Collision部件
报错信息
19:52:46.208 Infinite yield possible on 'ReplicatedStorage.__SCRIPTS.__VOICE_LINES:WaitForChild("Positions")' - Studio 19:52:46.208 Stack Begin - Studio 19:52:46.209 Script 'ReplicatedStorage.__SCRIPTS.__VOICE_LINES.VoicelineTrigger', Line 5 - Studio - VoicelineTrigger:5 19:52:46.209 Stack End - Studio
同时伴随Roblox核心模块无限等待警告,偶现脚本重复执行导致Studio崩溃。
修复方案
1. 解决资源加载超时问题
脚本启动时Positions等对象可能未完成加载,需添加加载等待与超时判断:
-- 等待游戏核心资源加载完成 repeat task.wait() until game:IsLoaded() local ReplicatedStorage = game:GetService("ReplicatedStorage") local Players = game:GetService("Players") -- 逐个加载关键对象,添加超时处理 local col = script.Parent:WaitForChild("Collision", 30) if not col then warn("Collision部件加载超时") return end local positionsFolder = script.Parent:WaitForChild("Positions", 30) if not positionsFolder then warn("Positions文件夹加载超时") return end local audioPositions = positionsFolder:GetChildren() local subtitleSeqFolder = script.Parent:WaitForChild("SubtitleSequence", 30) if not subtitleSeqFolder then warn("SubtitleSequence文件夹加载超时") return end local subtitleSequence = subtitleSeqFolder:GetChildren() -- 模块加载也添加超时 local audioModule = ReplicatedStorage:WaitForChild("__AUDIO", 10) if not audioModule then warn("__AUDIO模块加载失败") return end local audioFunc = require(audioModule) local gameUIModule = ReplicatedStorage:WaitForChild("__GAME_UI", 10) if not gameUIModule then warn("__GAME_UI模块加载失败") return end local gameUIFunc = require(gameUIModule)
2. 彻底杜绝重复触发
使用:Once()绑定事件,触发后立即断开连接并销毁碰撞体,避免任何重复执行可能:
local function onTouched() -- 立即断开事件并销毁碰撞体 touchedConnection:Disconnect() col:Destroy() -- 批量克隆并播放音频 for _, audioPosition in ipairs(audioPositions) do audioFunc.createSound(voiceline, audioPosition) end -- 异步启动字幕序列 task.spawn(RunSubtitleSequence) end -- 绑定一次性触发事件 local touchedConnection = col.Touched:Once(onTouched)
3. 优化字幕序列函数
缓存字幕文本对象,减少重复调用,添加属性超时判断,用task.wait()替代wait()提升性能:
local function RunSubtitleSequence() -- 缓存字幕对象,避免重复查找 local subtitleText = gameUIFunc.returnSubtitlesTextObject(Players.LocalPlayer) if not subtitleText then warn("无法获取字幕文本对象") return end for _, subtitle in ipairs(subtitleSequence) do -- 给Duration添加超时等待 local duration = subtitle:WaitForChild("Duration", 5) if not duration then warn("字幕[" .. subtitle.Name .. "]缺少Duration属性") continue end subtitleText.Text = subtitle.Value task.wait(duration.Value) end -- 清空字幕 subtitleText.Text = "" end
4. 脚本结构优化建议
将脚本放在StarterPlayerScripts或StarterCharacterScripts而非ReplicatedStorage,避免因复制导致多实例执行;若必须放在ReplicatedStorage,需添加单例判断确保只运行一次:
-- 单例判断,防止脚本多实例执行 if script:GetAttribute("HasRun") then return end script:SetAttribute("HasRun", true)
内容的提问来源于stack exchange,提问作者R0CK3T_DEV
相关产品推荐
相关产品推荐

