Performance 使用lua和Roblox Studio提高性能

Performance 使用lua和Roblox Studio提高性能,performance,lua,lag,roblox,heartbeat,Performance,Lua,Lag,Roblox,Heartbeat,我终于用lua和Roblox studio完成了我的第一个脚本。 目标是让一组瓷砖在玩家踩上去时改变颜色 这是我的密码: local parts = {} for k, v in pairs(game.Workspace:GetDescendants()) do if string.sub (v.name, 1, 4) == "Part" then table.insert(parts, v) end end local char = workspace:Wa

我终于用lua和Roblox studio完成了我的第一个脚本。 目标是让一组瓷砖在玩家踩上去时改变颜色

这是我的密码:

local parts = {}
for k, v in pairs(game.Workspace:GetDescendants()) do
    if string.sub (v.name, 1, 4) == "Part"  then
        table.insert(parts, v)
    end
end

local char = workspace:WaitForChild("localPlayer") 

local hrp = char:WaitForChild("HumanoidRootPart")

local newThread = coroutine.create(function()

game:GetService("RunService").Heartbeat:Connect(function()
    local charpos = hrp.Position

    for k, v in pairs (parts)do
        if (charpos - v.CFrame.Position).magnitude <= 6 then
            local pos = v.CFrame.Position
            for k, v in pairs(parts) do
                if v.CFrame.Position.X == pos.X or v.CFrame.Position.Z == pos.Z then
                    v.BrickColor = BrickColor.new("Really red")
                    print("touching")
                end
            end
            return
        else
            v.BrickColor = BrickColor.new("Medium stone grey")
            print("not touching")
        end
    end
end)

end)

coroutine.resume(newThread)

作为一个练习,看看我是否能让这个“多维数组”的新概念发挥作用。最后一行不行。如何访问数组中的元素?tx

微小变化-将新砖颜色的构造移出环路。它的值不会因未受影响的零件而改变,没有理由重复创建它

并查看打印大量调试信息是否会影响性能,因此请对打印内容进行注释


其次,您可能应该将块的网格重新组织为二维数组。因此,您不必扫描所有零件来查找具有相同X/Z坐标的零件。这也将为您提供快速找到最近的砖块的方法,这在常规网格上很简单。

您的函数不在协程中,只有与信号的连接是。但是,由于heartbeat代码正在运行每一个帧,因此使用协同路由将工作分派到另一个线程,而该线程直到下一个帧才会启动,这不会有多大帮助。因此,与其使用线程,不如尝试寻找最小化函数计算工作量的方法

打印语句可能会减慢速度,因此,当您知道逻辑工作时,请将其注释掉。使用平方根进行计算非常昂贵,因此我认为最好的优化方法是最小化距离检查的次数

我建议将Heartbeat函数作为一个更可靠的TouchEnded处理程序,但只有在知道有玩家在触摸它们的平台上才能使用它。然后,您可以使用部件的触摸处理程序来了解哪些平台有玩家

-- initialize some script globals
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

-- grab all the platforms and create a table of custom objects with data we care about
local platforms = {}
for _, part in ipairs(game.Workspace:GetDescendants()) do
    if string.sub (v.name, 1, 4) ~= "Part"  then
        continue
    end

    local platformData = {
        Part = part, -- the original object
        Touches = {}, -- a map of players actively touching it
    }

    -- initialize any events on these parts
    part.Touched:Connect(function(otherPart)
        -- when touched, check which player it is, and hold onto that information
        local player = Players:GetPlayerFromCharacter(part.Parent)
        if not player then
            warn(string.format("unexpected object touched a platform. Ignoring %s", part.Parent.Name))
            return
        end

        platformData.Touches[player.PlayerId] = player
    end)

    -- hold onto this data
    table.insert(platforms, platformData)
end

-- make a function that updates colors
RunService.Heartbeat:Connect(function()
    for _, platform in ipairs(platforms) do
        local isTouched = next(platform.Touches) ~= nil

        -- quick escape for inactive platforms
        if not isTouched then
            continue
        end

        -- check if the previous players are still touching it
        isTouched = false
        for id, player in pairs(platform.Touches) do
            local platPos = platform.Part.Position
            local hrp = player.Character.PrimaryPart
            local charPos = hrp.Position
            local dist = (platPos - charPos).magnitude

            if dist < 6 then
                isTouched = true
            else
                -- this player is no longer touching, remove them
                platform.Touches[id] = nil
            end
        end

        -- update the color of the platforms
        if isTouched then
            platform.Part.BrickColor = BrickColor.new("Really red")
        else
            platform.Part.BrickColor = BrickColor.new("Really blue")
        end
    end
end)
——初始化一些脚本全局变量
本地玩家=游戏:GetService(“玩家”)
本地运行服务=游戏:GetService(“运行服务”)
--抓取所有平台,创建一个包含我们关心的数据的自定义对象表
本地平台={}
对于u3;,参与ipairs(game.Workspace:getSubstanders())do
如果string.sub(v.name,1,4)~=“Part”,那么
持续
结束
本地平台数据={
Part=Part,--原始对象
触摸={},-一张玩家主动触摸它的地图
}
--初始化这些部件上的任何事件
部分。触摸:连接(功能(其他部分)
--触摸时,检查它是哪个播放器,并保留该信息
本地玩家=玩家:GetPlayerFromCharacter(part.Parent)
如果不是玩家的话
警告(string.format(“意外对象触及平台。忽略%s”,part.Parent.Name))
返回
结束
platformData.touchs[player.PlayerId]=玩家
(完)
--保留这些数据
表.插入(平台、平台数据)
结束
--创建一个更新颜色的函数
心跳:连接(函数()
对于u,IPAIR中的平台(平台)do
local isTouched=next(platform.touched)~=nil
--非活动平台的快速退出
如果不是我碰过的话
持续
结束
--检查之前的玩家是否仍在触摸它
isTouched=false
对于id,玩家成对(platform.touch)进行
本地平台位置=平台零件位置
本地hrp=player.Character.PrimaryPart
本地字符位置=hrp位置
局部距离=(platPos-charPos).震级
如果距离<6,则
isTouched=真
其他的
--此玩家不再接触,请将其移除
platform.touchs[id]=nil
结束
结束
--更新平台的颜色
如果我碰了那
platform.Part.BrickColor=BrickColor.new(“真红”)
其他的
platform.Part.BrickColor=BrickColor.new(“真蓝”)
结束
结束
(完)

我希望这有帮助!祝你好运

这是单人游戏吗?如果不是,两个玩家交叉的平台应该是什么颜色?谢谢你的评论。所以,我的想法是,每个玩家只看到他们本地机器的变化。我们的想法是,颜色可以帮助你确定下一步行动的方向。我不完全确定如何在这一点上实现这一点,虽然。可能是本地脚本而不是serverscriptservice脚本?我想先解决性能问题。你能分享一下这个麻烦的项目吗?如果它不够大,不能被视为产品:)谢谢你的评论。很抱歉问你,你能告诉我你的意思吗。从循环中取出任何东西都是破坏东西!我认为他们建议使用嵌套循环在网格中构建平台,而不是将它们从工作区中取出。我的意思是将部件存储在数组中,而不是存储在单个表中。这样,只需缩放/偏移玩家的坐标,就可以获得最近部分的行/列索引。无论字段大小如何,您都会立即得到最接近的部分。此代码不会高亮显示同一行和同一列中的所有平铺,我将对此进行编辑。我昨晚开始打这个答案。
-- initialize some script globals
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

-- grab all the platforms and create a table of custom objects with data we care about
local platforms = {}
for _, part in ipairs(game.Workspace:GetDescendants()) do
    if string.sub (v.name, 1, 4) ~= "Part"  then
        continue
    end

    local platformData = {
        Part = part, -- the original object
        Touches = {}, -- a map of players actively touching it
    }

    -- initialize any events on these parts
    part.Touched:Connect(function(otherPart)
        -- when touched, check which player it is, and hold onto that information
        local player = Players:GetPlayerFromCharacter(part.Parent)
        if not player then
            warn(string.format("unexpected object touched a platform. Ignoring %s", part.Parent.Name))
            return
        end

        platformData.Touches[player.PlayerId] = player
    end)

    -- hold onto this data
    table.insert(platforms, platformData)
end

-- make a function that updates colors
RunService.Heartbeat:Connect(function()
    for _, platform in ipairs(platforms) do
        local isTouched = next(platform.Touches) ~= nil

        -- quick escape for inactive platforms
        if not isTouched then
            continue
        end

        -- check if the previous players are still touching it
        isTouched = false
        for id, player in pairs(platform.Touches) do
            local platPos = platform.Part.Position
            local hrp = player.Character.PrimaryPart
            local charPos = hrp.Position
            local dist = (platPos - charPos).magnitude

            if dist < 6 then
                isTouched = true
            else
                -- this player is no longer touching, remove them
                platform.Touches[id] = nil
            end
        end

        -- update the color of the platforms
        if isTouched then
            platform.Part.BrickColor = BrickColor.new("Really red")
        else
            platform.Part.BrickColor = BrickColor.new("Really blue")
        end
    end
end)