我的代码就像在一个while循环中一样,即使它不是

Posted

技术标签:

【中文标题】我的代码就像在一个while循环中一样,即使它不是【英文标题】:My code acts like it is on a while loop, even though its not 【发布时间】:2021-08-29 22:27:30 【问题描述】:

我想让它在每次结束后播放 15 次警报。 我希望它能够工作,然后打印它已经完成。但是,它会无限打印它并最终冻结 Roblox Studio。

我已经研究和研究,声音结束事件仅在声音结束时触发,所以它不是多次触发的事件。我没有在 *** 上看到答案(如预期的那样)。

这是我的本地脚本:

-- 15 times
local warheadalarmevent = game.ReplicatedStorage:WaitForChild("WarheadAlarm")
warheadalarmevent.OnClientEvent:Connect(function()
    script.WarheadAlarm:Play() -- 1st time
    script.WarheadAlarm.Ended:Connect(function()
        script.WarheadAlarm:Play() -- 2nd time
        script.WarheadAlarm.Ended:Connect(function()
            script.WarheadAlarm:Play() -- 3rd time
            script.WarheadAlarm.Ended:Connect(function()
                script.WarheadAlarm:Play() -- 4th time
                script.WarheadAlarm.Ended:Connect(function()
                    script.WarheadAlarm:Play() -- 5th time
                    script.WarheadAlarm.Ended:Connect(function()
                        script.WarheadAlarm:Play() -- 6th time
                        script.WarheadAlarm.Ended:Connect(function()
                            script.WarheadAlarm:Play() -- 7th time
                            script.WarheadAlarm.Ended:Connect(function()
                                script.WarheadAlarm:Play() -- 8th time
                                script.WarheadAlarm.Ended:Connect(function()
                                    script.WarheadAlarm:Play() -- 9th time
                                    script.WarheadAlarm.Ended:Connect(function()
                                        script.WarheadAlarm:Play() -- 10th time
                                        script.WarheadAlarm.Ended:Connect(function()
                                            script.WarheadAlarm:Play() -- 11th time
                                            script.WarheadAlarm.Ended:Connect(function()
                                                script.WarheadAlarm:Play() -- 12th time
                                                script.WarheadAlarm.Ended:Connect(function()
                                                    script.WarheadAlarm:Play() -- 13th time
                                                    script.WarheadAlarm.Ended:Connect(function()
                                                        script.WarheadAlarm:Play() -- 14th time
                                                        script.WarheadAlarm.Ended:Connect(function()
                                                            script.WarheadAlarm:Play() -- 15th time
                                                            script.WarheadAlarm.Ended:Connect(function()
                                                                print("15 times")
                                                            end)
                                                        end)
                                                    end)
                                                end)
                                            end)
                                        end)
                                    end)
                                end)
                            end)
                        end)
                    end)
                end)
            end)
        end)
    end)
end)

这是我的脚本(触发远程事件):

local alreadydone = false

function myfunction()
    if alreadydone == true then
        return
    end
    
    alreadydone = true

    script.Parent.Parent.Button.Transparency = 1
    script.Parent.Parent.FakeButton.Transparency = 0
    script.Parent.Parent.Button.ClickDetector.MaxActivationDistance = 0

    wait(.2)
    script.Parent.Parent.Button.Transparency = 0
    script.Parent.Parent.FakeButton.Transparency = 1
    game.ReplicatedStorage.WarheadAlarm:FireAllClients()
    game.Workspace.MordernTV.TV.SCREEN.SurfaceGui.Status.Text = "PRIMING"
    game.Workspace.MordernTV.TV.SCREEN.SurfaceGui.Status.TextColor3 = Color3.new(1, 1, 0)
    wait(30)
    game.Workspace.MordernTV.TV.SCREEN.SurfaceGui.Status.Text = "PRIMED, ENGAGING.."
    game.Workspace.MordernTV.TV.SCREEN.SurfaceGui.Status.TextColor3 = Color3.new(0, 1, 0)                      
end                            

script.Parent.ClickDetector.MouseClick:connect(myfunction)

我没有多次点击它或什么,发生了什么?

【问题讨论】:

【参考方案1】:

您的代码中发生的情况是,您将越来越多的侦听器连接到同一事件,而从未断开任何连接。每次闹钟播放时,您都会连接另一个侦听器,以及连接更多侦听器的另一个函数。 Studio 崩溃是因为您创建了一个无限循环的函数,这些函数连接了函数,最终有太多的函数需要处理并且 Studio 崩溃了。

除了连接到 Sound.Ended 信号,您还可以调用信号的 Wait() 函数,该函数将在事件发生之前产生线程。因此,您可以在循环中使用它来确保警报一个接一个地触发,并跟踪警报已播放了多少次。

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local warheadAlarm = script.WarheadAlarm
local warheadAlarmEvent = ReplicatedStorage:WaitForChild("WarheadAlarm")

-- create a debounce flag
local isAlarmPlaying = false

warheadAlarmEvent.OnClientEvent:Connect(function()
    -- if alarm is already playing, escape
    if isAlarmPlaying then
        return
    end

    -- flip the debounce flag
    isAlarmPlaying = true

    -- play the alarm, and wait for each sound to finish
    local callCount
    for callCount = 0, 15, 1 do
        warheadAlarm:Play()
        warheadAlarm.Ended:Wait()
    end

    -- do the thing
    print("15 times")

    -- reset the debounce flag
    isAlarmPlaying = false
end)

【讨论】:

【参考方案2】:

(免责声明我并不真正了解 Roblox,但我认为这是一个很好的猜测,我确实读过一些关于它的信息。)

当您将函数连接到结束事件时,每次声音结束时都会调用它,而不仅仅是下一次。在第一次之后,将有多个功能连接到结束的事件,您可能不想要这些功能。而且,即使在第 15 次之后,前 14 个连接仍然存在并试图重放声音(一次多次播放声音也可能不好,将越来越多的功能连接到事件可能很快就会引起大问题随着连接数呈指数增长)。

这可能可以通过在第一次触发时断开每个连接来解决。但是,将一个函数连接到事件并使用一个最多为 15 的变量来确定是否重新触发声音可能会更容易。然后,如果您想再次使用声音对象,我想您仍然应该断开连接。

未经测试:

warheadalarmevent.OnClientEvent:Connect(function()
  script.WarheadAlarm:Play()
  local n = 0
  local connection
  connection = script.WarheadAlarm.Ended:Connect(function()
    n = n + 1
    if n < 15 then
      script.WarheadAlarm:Play()
    else
      connection:Disconnect()
    end
  end)
end)

(请注意,该连接可能仍适用于任何尝试播放 script.WarheadAlarm 的内容,因此如果多个事物同时尝试播放此声音,您可能需要进一步重新考虑您的方法。)

【讨论】:

以上是关于我的代码就像在一个while循环中一样,即使它不是的主要内容,如果未能解决你的问题,请参考以下文章

C : 使用 && 运算符时是不是存在“惰性求值”,就像在 C++ 中一样?

DatabaseReference setValue 像在循环中一样工作

如何在php中创建SOAP请求,就像在SoapUI中一样?

如何向列表添加编辑按钮,就像在向左滑动列表项时删除按钮一样

就像在 facebook 应用程序中一样高效流畅地滚动顶部视图

three.js如何使纹理“生成”纹理坐标,就像搅拌器循环一样