为啥 Roblox 和 Roblox Studio 在运行某些没有错误代码的脚本时都会崩溃?

Posted

技术标签:

【中文标题】为啥 Roblox 和 Roblox Studio 在运行某些没有错误代码的脚本时都会崩溃?【英文标题】:Why does Roblox & Roblox Studio both crash when running certain scripts with no error code?为什么 Roblox 和 Roblox Studio 在运行某些没有错误代码的脚本时都会崩溃? 【发布时间】:2021-05-24 15:16:03 【问题描述】:

所以这是交易,我正在开发一款类似于谋杀之谜的游戏,系统的这一部分是开始回合并向玩家展示他们的角色,然后是地图。除了它曾经可以工作而且我没有故意对脚本做任何会影响它的事情,所以当这部分执行时游戏会崩溃。我所知道的是它开始显示角色并且经常这样做,它还会播放声音并显示正确的描述,但是它在那之后就崩溃了,有时在角色显示之前就崩溃了。我已将 RoundStarter 事件触发时运行的函数附加到客户端。

服务器不会崩溃,但所有客户端都会崩溃,但并非都在完全相同的时间;以前,当出现错误时,我能够识别错误消息,但没有一个客户端抛出任何明确的问题。

在 Roblox Studio 的测试模式下,当角色显示时,他们会在鼓声效果后冻结,但没有错误,服务器似乎运行正常。在 Roblox 中运行时几乎会发生同样的事情。

客户端脚本

    ReplicatedStorage.Players.Events.RoundStarter.OnClientEvent:Connect(function(Role,Map)
    local player = game.Players.LocalPlayer

    player.CameraMode = Enum.CameraMode.LockFirstPerson
    script.Parent.RoundGui.RoundEnd.Visible = false
    game.Players.LocalPlayer.NameDisplayDistance = 0
    CURRENTROLE = Role
    CURRENTMAP = Map
    script.Parent.RoundGui.Enabled = true

    script.Parent.RoundGui.RoundStarter.Visible = true
    script.Parent.RoundGui.RoundStarter.Fader.Visible = true
    script.Parent.RoundGui.RoundStarter.Fader.BackgroundTransparency = 0
    script.Parent.RoundGui.RoundStarter.RoleDescription.Visible = false
    script.Parent.RoundGui.RoundStarter.RoleName.Visible = false
    script.Parent.RoundGui.RoundStarter.Text.Visible = true
    local transp = 0
    for i = 1,50,1 do
        transp += 0.05
        script.Parent.RoundGui.RoundStarter.Fader.BackgroundTransparency = transp
        wait(.1)
    end 
    script.Parent.RoundGui.RoundStarter.DR:Play()
    script.Parent.RoundGui.RoundStarter.RoleName.Visible = true
    script.Parent.RoundGui.RoundStarter.RoleName.Text = Role
    script.Parent.RoundGui.RoundStarter.RoleDescription.Visible = true

    if Role == "Civilian" then
        script.Parent.RoundGui.RoundStarter.RoleDescription.Text = "Your Job is to help the Inspector find the shadow... Work to figure them out and stop them before it's too late! Don't tell anyone your Role!"
        script.Parent.RoundGui.RoundStarter.RoleName.TextColor3 = Color3.fromRGB(0, 255, 17)
    elseif Role == "Shadow" then
        script.Parent.RoundGui.RoundStarter.RoleName.TextColor3 = Color3.fromRGB(255, 0, 0)
        script.Parent.RoundGui.RoundStarter.RoleDescription.Text = "It's time... Infiltrate the crowd, gain their trust and kill the inspector to win! By killing another player, You can take on their form and blend in with the Civilians. More help will be on left of the screen. Don't tell anyone your Role!"        
    elseif Role == "Inspector"  then
        script.Parent.RoundGui.RoundStarter.RoleName.TextColor3 = Color3.fromRGB(0, 38, 255)
        script.Parent.RoundGui.RoundStarter.RoleDescription.Text = "You are nominated to fight the Shadow and eliminate them. You must work with the Civilians to figure out who the Shadow is, if you die you lose. Don't tell anyone your Role!"      
    end
    wait(10)
    script.Parent.RoundGui.RoundStarterMap.Visible = true
    script.Parent.RoundGui.RoundStarterMap.Fader.Visible = true
    script.Parent.RoundGui.RoundStarterMap.MapDescription.Visible = false
    script.Parent.RoundGui.RoundStarterMap.MapName.Visible = false

    local transp = 0
    for i = 1,50,1 do
        transp += 0.05
        script.Parent.RoundGui.RoundStarterMap.Fader.BackgroundTransparency = transp
        wait(.1)
    end
    script.Parent.RoundGui.RoundStarterMap.MapName.Visible = true
    script.Parent.RoundGui.RoundStarterMap.MapName.Text = Map
    script.Parent.RoundGui.RoundStarter.Dun:Play()

    if Map == "The Office" then
        script.Parent.RoundGui.RoundStarterMap.MapDescription.Text = "A classic map based in an Office building, in a power cut, near midnight. With an outdoor and Indoor area to explore, will you survive?"

    elseif Map =="The Village" then

        script.Parent.RoundGui.RoundStarterMap.MapDescription.Text = "The original map based in a small villiage with numerous buildings and areas to explore."     

    end
    script.Parent.RoundGui.RoundStarterMap.MapDescription.Visible = true
    wait(10)
    script.Parent.RoundGui.RoundEnd.Visible = false
    script.Parent.RoundGui.RoundStarterMap.Visible = false
    script.Parent.RoundGui.RoundStarter.Visible = false
end)
--This is the next function in the code that should be executed at a similar time to the above one (It should have an InMap value of true.
ReplicatedStorage.Players:WaitForChild(player.Name).InMap.Changed:Connect(function()
    data = game.ReplicatedStorage.GetPlayerDataCS:InvokeServer()
    if ReplicatedStorage.Players[player.Name].InMap.Value == false then

        --StartGUI:SetCoreGuiEnabled(Enum.CoreGuiType.PlayerList, true)
        player.CameraMode = Enum.CameraMode.Classic
        --StartGUI:SetCoreGuiEnabled(Enum.CoreGuiType.Chat,true)
        script.Parent.LobbyGui.Enabled = true
        script.Parent.RoundGui.Enabled = false
        wait()

    else

        if CURRENTROLE == "Shadow" then
            script.Parent.RoundGui.ShadowPanel.Visible = true
            script.Parent.RoundGui.CivPanel.Visible = false
            script.Parent.RoundGui.InsPanel.Visible = false
            
            if data then
                if data.EquippedAbility ~="None" and  data.EquippedAbility ~="" then
                    script.Parent.RoundGui.ShadowPanel[data.EquippedAbility].Visible = true
                end 
            end
        elseif CURRENTROLE == "Inspector" then
            script.Parent.RoundGui.ShadowPanel.Visible = false
            script.Parent.RoundGui.CivPanel.Visible = false
            script.Parent.RoundGui.InsPanel.Visible = true      
        else
            script.Parent.RoundGui.ShadowPanel.Visible = false
            script.Parent.RoundGui.CivPanel.Visible = true
            script.Parent.RoundGui.InsPanel.Visible = false     
        end

        --StartGUI:SetCoreGuiEnabled(Enum.CoreGuiType.PlayerList, false)
        --StartGUI:SetCoreGuiEnabled(Enum.CoreGuiType.Chat,true)
        script.Parent.LobbyGui.Enabled = false
        script.Parent.RoundGui.Enabled = true
        wait()
    end 
end)

这也是服务器上应该靠近事件的脚本。

local replicatedstor = game:GetService("ReplicatedStorage")
local playersinthemap = 
local playersinserver = game.Players:GetPlayers()   
local maplist = "The Village"
local TESTINGMODE = false
local goodwin = false
local COUNT = 0
local deadpool = 
local DataStoreService = game:GetService("DataStoreService")
local Datastore = DataStoreService:GetDataStore("THE_MASQUERADE_TEST2")
function UpdateStatuses(Playerr,NewStatus)

    local c = Playerr
    



    if NewStatus == "Lobby" or NewStatus == "AFK" then
        if game.ReplicatedStorage.Players[c.Name].Status.Value == "Shadow" then
            script.RoundsInProgress.Value = false
            goodwin = true
        elseif game.ReplicatedStorage.Players[c.Name].Status.Value == "Inspector" then
            script.RoundsInProgress.Value = false
            goodwin = false 
        end

        game.ReplicatedStorage.Players[c.Name].InMap.Value = false
        if table.find(playersinthemap,c,1)~= nil then
            local index = table.find(playersinthemap,c,1)
            table.remove(playersinthemap,index)

        end



    end
    game.ReplicatedStorage.Players[c.Name].Status.Value = NewStatus
    if #playersinthemap <= 2 and script.RoundsInProgress.Value == true then
        script.RoundsInProgress.Value = false
        goodwin = false         
    end
end



game.ReplicatedStorage.Players.Events.SetStatus.OnServerEvent:Connect(function(Player,Status)
    if Status ~= nil then

        UpdateStatuses(Player,Status)

    else
        print ("Tried to change status of Player but the given status was nil.")
    end
end)

while true do   

    
    while script.RoundsRunning.Value == true do
        game.ReplicatedStorage.Players.Events.Notify:FireAllClients("Intermission...","L",false)
        --game.ReplicatedStorage.Game.Intermission:Fire(30)
        --game.ReplicatedStorage.Game.Intermission.Event:Wait()
        wait(35)
        game.Workspace.Lobby.DATABOARD.SurfaceGui.Frame.Title.Text = "Round starting soon..."
        --game.ReplicatedStorage.Players.Events.Notify:FireAllClients("Round starting soon...","L",true)
        --game.Workspace.Lobby.DATABOARD.SurfaceGui.Frame.Time.Text = ""
        if not game.Workspace.Map then
            playersinthemap = 
            local Mapfolder = Instance.new("Folder",game.Workspace)
            Mapfolder.Name = "Map"
        end

        playersinserver = game.Players:GetPlayers()

        wait(10)
        playersinserver = game.Players:GetPlayers() 
        if #playersinserver >= 4 or (TESTINGMODE == true and #playersinserver >= 3) then
            game.Workspace.Lobby.DATABOARD.SurfaceGui.Frame.Title.Text = "Round loading..."
            game.ReplicatedStorage.Players.Events.Notify:FireAllClients("Loading the round now...","L",false)
            playersinserver = game.Players:GetPlayers() 
            local chosenMapIndex = math.random(#maplist)
            local chosenMapName = maplist[chosenMapIndex]
            local chosenShadowIndex = math.random(#playersinserver)
            local chosenShadow = playersinserver[chosenShadowIndex]
            local chosenInspectorIndex = math.random(#playersinserver)  
            local chosenInspector = playersinserver[chosenInspectorIndex]
            while chosenInspector == chosenShadow do
                chosenInspectorIndex = math.random(#playersinserver)    
                chosenInspector = playersinserver[chosenInspectorIndex]
            end
            local playernumber = playersinserver
            COUNT = 0
            while COUNT ~= #playersinserver do
                COUNT += 1
                local playername = playersinserver[COUNT].Name
                print (playersinserver)
                print ("Player trying to send role data:"..playername)
                if playersinserver[COUNT] == chosenShadow then
                    game.ReplicatedStorage.Players.Events.RoundStarter:FireClient(playersinserver[COUNT],"Shadow",chosenMapName)
                    game.ReplicatedStorage.Players[playersinserver[COUNT].Name].Status.Value = "Shadow"
                    --temp = game.ReplicatedStorage.ReadStatus:Invoke(playername,"Shadow")
                elseif playersinserver[COUNT] == chosenInspector then
                    game.ReplicatedStorage.Players.Events.RoundStarter:FireClient(playersinserver[COUNT],"Inspector",chosenMapName)
                    game.ReplicatedStorage.Players[playersinserver[COUNT].Name].Status.Value = "Inspector"

                    --temp = game.ReplicatedStorage.ReadStatus:Invoke(playername,"Inspector")

                else
                    game.ReplicatedStorage.Players.Events.RoundStarter:FireClient(playersinserver[COUNT],"Civilian",chosenMapName)
                    game.ReplicatedStorage.Players[playersinserver[COUNT].Name].Status.Value = "Civilian"
                    --temp = game.ReplicatedStorage.ReadStatus:Invoke(playername,"Civilian")

                end
            end         

            wait()
            local MapInServerStorage = game.ServerStorage.Maps:FindFirstChild(chosenMapName)
            local LoadedMap = MapInServerStorage:Clone()
            LoadedMap.Parent = game.Workspace.Map
            local spawns = 
            for i,c in pairs(LoadedMap:GetDescendants()) do

                if c.Name == "Spawn" then
                    table.insert(spawns,1,c)
                end
            end
            COUNT = 0
            local i = COUNT
            while COUNT ~= #playersinserver do
                COUNT += 1
                print ("Setting Character locations. Loop:"..COUNT)
                local spawnlistindex = math.random(#spawns)
                playersinserver[COUNT].Character:SetPrimaryPartCFrame(spawns[spawnlistindex].CFrame)
                --playersinserver[COUNT].Character:SetPrimaryPartCFrame(LoadedMap.Spawns.Spawn.CFrame)
                table.insert(playersinthemap,1,playersinserver[COUNT])
                playersinserver[COUNT].NameDisplayDistance = 0
                game.ReplicatedStorage.Players:FindFirstChild(playersinserver[COUNT].Name).InMap.Value = true
                if playersinserver[COUNT] == chosenInspector then
                    local data = game.ReplicatedStorage.GetPlayerData:Invoke(chosenInspector)
                    
                    Pistl = game.ServerStorage.Guns[data.EquippedSkin]:Clone()
                    Pistl.Parent = playersinserver[COUNT].Backpack
                end
            end
            print ("Round starting...")
            --This is then followed by the rest of the round system which should be working but I have cut it to try to shorten the amount of reading but can be supplied if needed. It is closed correctly.

我已尝试将代码保持在最低限度,但它可能在任何地方,并且由于没有明显的与脚本相关的错误代码,我请求以某种方式提供帮助。

还有其他原因可能导致它,但这正在成为一个真正的问题,特别是因为它曾经有效,而且我已经包括了所有可能的嫌疑人,但如果这些不是,我很乐意提供任何其他信息反正也不对。

如果您想亲眼看看会发生什么,您需要 4 个 Roblox 帐户或 3 个额外的朋友。 这是 Roblox 上的游戏:The Masquerade

如果需要其他任何内容,请随时告诉我,感谢您的阅读和任何可能的帮助。 (只是让你知道,我对我正在使用的所有功能和东西进行了大量研究,但我找不到任何问题,它只是冻结和崩溃)。

我得到的唯一错误代码是:

 Start Process Exception...
 Uploading crash analytics 
 Done uploading crash analytics

【问题讨论】:

【参考方案1】:

有一些随机的wait() 语句没有任何参数,它们不应该出现在你的代码中。这很可能会挂断服务器/客户端。

此外,您似乎有一些没有任何wait() 的while 循环。这是一个非常常见的问题,它会阻止客户端执行脚本。尝试至少添加 wait(0.01) 到每个还没有的 while true 循环的末尾。

客户端中也可能出现这种情况(例如没有参数的孤独的wait()),但这是您的服务器脚本的修改版本:

while true do   


while script.RoundsRunning.Value == true do
    game.ReplicatedStorage.Players.Events.Notify:FireAllClients("Intermission...","L",false)
    --game.ReplicatedStorage.Game.Intermission:Fire(30)
    --game.ReplicatedStorage.Game.Intermission.Event:Wait()
    wait(35)
    game.Workspace.Lobby.DATABOARD.SurfaceGui.Frame.Title.Text = "Round starting soon..."
    --game.ReplicatedStorage.Players.Events.Notify:FireAllClients("Round starting soon...","L",true)
    --game.Workspace.Lobby.DATABOARD.SurfaceGui.Frame.Time.Text = ""
    if not game.Workspace.Map then
        playersinthemap = 
        local Mapfolder = Instance.new("Folder",game.Workspace)
        Mapfolder.Name = "Map"
    end

    playersinserver = game.Players:GetPlayers()

    wait(10)
    playersinserver = game.Players:GetPlayers() 
    if #playersinserver >= 4 or (TESTINGMODE == true and #playersinserver >= 3) then
        game.Workspace.Lobby.DATABOARD.SurfaceGui.Frame.Title.Text = "Round loading..."
        game.ReplicatedStorage.Players.Events.Notify:FireAllClients("Loading the round now...","L",false)
        playersinserver = game.Players:GetPlayers() 
        local chosenMapIndex = math.random(#maplist)
        local chosenMapName = maplist[chosenMapIndex]
        local chosenShadowIndex = math.random(#playersinserver)
        local chosenShadow = playersinserver[chosenShadowIndex]
        local chosenInspectorIndex = math.random(#playersinserver)  
        local chosenInspector = playersinserver[chosenInspectorIndex]
        while chosenInspector == chosenShadow do
            chosenInspectorIndex = math.random(#playersinserver)    
            chosenInspector = playersinserver[chosenInspectorIndex]
        end
        local playernumber = playersinserver
        COUNT = 0
        while COUNT ~= #playersinserver do
            COUNT += 1
            local playername = playersinserver[COUNT].Name
            print (playersinserver)
            print ("Player trying to send role data:"..playername)
            if playersinserver[COUNT] == chosenShadow then
                game.ReplicatedStorage.Players.Events.RoundStarter:FireClient(playersinserver[COUNT],"Shadow",chosenMapName)
                game.ReplicatedStorage.Players[playersinserver[COUNT].Name].Status.Value = "Shadow"
                --temp = game.ReplicatedStorage.ReadStatus:Invoke(playername,"Shadow")
            elseif playersinserver[COUNT] == chosenInspector then
                game.ReplicatedStorage.Players.Events.RoundStarter:FireClient(playersinserver[COUNT],"Inspector",chosenMapName)
                game.ReplicatedStorage.Players[playersinserver[COUNT].Name].Status.Value = "Inspector"

                --temp = game.ReplicatedStorage.ReadStatus:Invoke(playername,"Inspector")

            else
                game.ReplicatedStorage.Players.Events.RoundStarter:FireClient(playersinserver[COUNT],"Civilian",chosenMapName)
                game.ReplicatedStorage.Players[playersinserver[COUNT].Name].Status.Value = "Civilian"
                --temp = game.ReplicatedStorage.ReadStatus:Invoke(playername,"Civilian")

            end
        end         

        -- wait()     useless wait
        local MapInServerStorage = game.ServerStorage.Maps:FindFirstChild(chosenMapName)
        local LoadedMap = MapInServerStorage:Clone()
        LoadedMap.Parent = game.Workspace.Map
        local spawns = 
        for i,c in pairs(LoadedMap:GetDescendants()) do

            if c.Name == "Spawn" then
                table.insert(spawns,1,c)
            end
        end
        COUNT = 0
        local i = COUNT
        while COUNT ~= #playersinserver do
            COUNT += 1
            print ("Setting Character locations. Loop:"..COUNT)
            local spawnlistindex = math.random(#spawns)
            playersinserver[COUNT].Character:SetPrimaryPartCFrame(spawns[spawnlistindex].CFrame)
            --playersinserver[COUNT].Character:SetPrimaryPartCFrame(LoadedMap.Spawns.Spawn.CFrame)
            table.insert(playersinthemap,1,playersinserver[COUNT])
            playersinserver[COUNT].NameDisplayDistance = 0
            game.ReplicatedStorage.Players:FindFirstChild(playersinserver[COUNT].Name).InMap.Value = true
            if playersinserver[COUNT] == chosenInspector then
                local data = game.ReplicatedStorage.GetPlayerData:Invoke(chosenInspector)
                
                Pistl = game.ServerStorage.Guns[data.EquippedSkin]:Clone()
                Pistl.Parent = playersinserver[COUNT].Backpack
            end
            wait(0.01)
        end
        wait(0.01)
        end

这些只是粗略的步骤,因此请按照您希望的方式将更改植入您的代码中。

【讨论】:

您好,感谢您的回复,我已经在服务器和客户端脚本中实现了很多wait(0.01)s;尽管稍微提高了质量并进入了地图阶段,但在回合完全开始之前它仍然崩溃。 此时唯一想到的就是做一些基本的调试。尝试在两个脚本的不同位置添加几个断点,看看代码从哪里开始中断。另一种粗略的解决方案可能是每隔几十行代码放置一些print("some random text")。它应该做同样的事情。这应该概述了脚本开始中断的时间点,因此您可以稍微缩小罪魁祸首。

以上是关于为啥 Roblox 和 Roblox Studio 在运行某些没有错误代码的脚本时都会崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的roblox gui在studio的测试区显示而在游戏中却没有

Roblox Studio 未加载

循环中的 Roblox Studio Lua if 语句

如何在 Roblox Studio 中移动网格

为啥实例:新功能不在实例 API 页面上(roblox)

Roblox Studio 游戏通行证购买失败