You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Roblox Studio中SoundId无法变更且RemoteEvent重复触发问题排查

问题根源与修复方案

核心问题

1. 服务端无法感知客户端的Sound状态

服务端代码里local currentlyPlaying = plr.Songs.CurrentlyPlaying.Sound读取的是服务端Player对象中的Sound实例,但客户端LocalScript是在本地Player副本里销毁并重建Sound——Roblox中客户端对Player对象的修改只会在本地生效,服务端完全看不到客户端的SoundId变更。这就导致服务端每次检测到触碰时,都会错误地认为当前播放的SoundId和目标不一致,反复触发RemoteEvent。

2. Touched事件的重复触发特性

Roblox的Touched事件会在碰撞持续期间多次触发(比如玩家站在方块上时),即使没有状态变化,也会不断执行判断逻辑,进一步加剧了RemoteEvent的重复调用。


修复方案

1. 服务端维护玩家播放状态(关键修复)

让服务端自己跟踪每个玩家当前播放的SoundId,不再依赖客户端的Sound实例:

修改后的服务端Script:

local mySong = script.Parent:FindFirstChildOfClass("Sound")
local musicBox = script.Parent
local players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage.PlayMusic

-- 存储每个玩家当前播放的SoundId
local playerCurrentSongs = {}
-- 触碰冷却,避免短时间重复触发
local touchCooldowns = {}
local COOLDOWN_TIME = 2

musicBox.Touched:Connect(function(hit)
    local char = hit.Parent:FindFirstChild("Humanoid")
    if not char then return end
    
    local plr = players:GetPlayerFromCharacter(char.Parent)
    if not plr then return end

    -- 检查冷却
    if touchCooldowns[plr.UserId] and os.clock() - touchCooldowns[plr.UserId] < COOLDOWN_TIME then
        return
    end
    touchCooldowns[plr.UserId] = os.clock()

    local targetSoundId = mySong and mySong.SoundId
    if not targetSoundId then
        warn("No sound found in musicBox")
        return
    end

    -- 检查玩家当前是否已经在播放目标音效
    if playerCurrentSongs[plr.UserId] == targetSoundId then
        return
    end

    -- 更新服务端记录的状态
    playerCurrentSongs[plr.UserId] = targetSoundId
    -- 通知客户端切换音效
    remoteEvent:FireClient(plr, mySong)
end)

-- 玩家离开时清理记录
players.PlayerRemoving:Connect(function(plr)
    playerCurrentSongs[plr.UserId] = nil
    touchCooldowns[plr.UserId] = nil
end)

2. 优化客户端代码(减少开销)

不需要每次销毁重建Sound,直接修改现有Sound的SoundId即可:

修改后的客户端LocalScript:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage.PlayMusic
local player = Players.LocalPlayer

local function changeMusic(newSong)
    local song1 = player.Songs.CurrentlyPlaying:FindFirstChildOfClass("Sound")
    if song1 then
        song1:Stop()
        song1.SoundId = newSong.SoundId
        song1:Play()
    else
        -- 没有Sound实例时再创建
        song1 = Instance.new("Sound")
        song1.SoundId = newSong.SoundId
        song1.Parent = player.Songs.CurrentlyPlaying
        song1:Play()
    end
end

remoteEvent.OnClientEvent:Connect(changeMusic)

内容的提问来源于stack exchange,提问作者Rezno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 22:52:44