使用 lua 和 Roblox Studio 提高性能

Improve performance using lua and Roblox Studio

我终于使用 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)

这个有效:

但是我的项目需要更多的瓷砖和更多的颜色。当我增加平台数量等时,程序变得非常卡顿。

gif 并没有真正显示出有多延迟,但它变得越来越糟,播放大约一分钟后,您几乎无法有效地控制播放器。

如您所见,我尝试将我的函数放在协同例程中,但这没有帮助。我对 lua 和 尝试 制作游戏非常陌生,所以我真的不知道如何提高性能。延迟越来越严重的事实似乎表明内存没有得到有效释放?我以为这是自动发生的。无论如何,非常感谢任何帮助。

根据建议,我尝试了这个:

Hi, I have tried this:

    local Platform = {}
    local maPart = Platform.part
    local function makePart(pX,pY,pZ)
        maPart = Instance.new("Part", workspace)
        maPart.Position = Vector3.new(pX,pY,pZ)
        maPart.Size = Vector3.new(10,1,10)
        return maPart
    end

    local columns = {}
    local rows = {}

    for i = 1, 12 do
        columns[i] = rows
        table.insert(columns, rows)
        for j = 1, 12 do
            maPart = makePart(i*16,0,j*16)
            rows[j] = maPart
            table.insert(rows, maPart)
        end
    end

    columns[1].[1].BrickColor = BrickColor.new("Really blue")

作为练习,看看我能否让 'multi dimensional arrays' 的这个新概念发挥作用。最后一行不起作用。我将如何访问数组中数组中的元素?发送

小改动 - 移出了新 BrickColor 构造的循环。它的值不会在未受影响的部分发生变化,没有理由重复创建它。

并查看打印大量调试信息是否会影响性能,因此注释掉打印。

其次,也许你应该将方块的网格重新组织成二维数组。因此,您不必扫描所有零件即可找到具有相同 X/Z 坐标的零件。这也将为您提供快速找到最近的砖块的方法,这在规则网格上是微不足道的。

您的函数不在协程内,只有与信号的连接在。但是,由于心跳代码是每个帧的 运行,因此使用协程将工作分派到另一个线程,该线程直到下一帧才会启动,这无济于事。因此,不要使用线程,而是尝试寻找最小化函数计算量的方法。

打印语句会减慢速度,所以当您知道逻辑有效时,请将其注释掉。平方根的计算是昂贵的,所以我认为最好的优化是尽量减少距离检查的次数。

我建议让 Heartbeat 函数充当更可靠的 TouchEnded 处理程序,但只能在知道有玩家触摸它们的平台上运行。然后您可以使用部件的 Touched 处理程序来了解哪些平台有玩家。

-- 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)

希望对您有所帮助!祝你好运!