使用lua和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和_尝试_制作游戏还很新,所以我真的不知道如何提高性能。卡顿越来越严重似乎表明内存没有有效释放?我假设这是自动发生的。无论如何,非常感谢任何帮助。

在得到建议后,我尝试了这个:

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

作为一个练习,看看我能否让这个对我来说新的概念的“多维数组”工作。最后一行不起作用。如何访问数组内部的数组中的元素?谢谢

点赞
用户5675002
用户5675002

Minor change

  • 将构建新的 BrickColor 的循环移出。该值在未受影响的部分不发生变化,因此不必重复创建。

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

其次,可能应该将块的网格重新组织成二维数组。这样,您就不必扫描所有部分以找到具有相同 X/Z 坐标的部分。这还将为您提供一种快速找到最近的 Brick 的方法,在正常的网格上是微不足道的。

2019-12-26 14:24:10
用户2860267
用户2860267

你的函数不在协程中,只有与信号的连接在协程中。但由于心跳代码每一帧都在运行,使用协程将工作分派到下一帧才启动的不同线程中不会有太大的帮助。因此,而不是使用线程,请尝试寻找减少函数计算工作量的方法。

当逻辑正常工作时,请将打印语句注释掉,因为它们会减缓速度。带平方根的计算很昂贵,因此我认为最好的优化是尽量减少距离检查的数量。

我建议使Heartbeat函数作为更可靠的TouchEnded处理程序,但只在知道它们有玩家接触的平台上进行工作。然后,您可以使用零件的Touched处理程序来知道哪些平台有玩家。

-- 初始化一些脚本全局变量
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

-- 获取所有平台并创建一个包含我们关心的数据的自定义对象表
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, -- 原始对象
        Touches = {}, -- 一个激活状态下接触到它的玩家映射表
    }

    -- 初始化这些零件上的任何事件
    part.Touched:Connect(function(otherPart)
        -- 当接触到零件时,检查它是哪个玩家,并保留该信息
        local player = Players:GetPlayerFromCharacter(part.Parent)
        if not player then
            warn(string.format("意外的对象触碰了平台。忽略%s", part.Parent.Name))
            return
        end

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

    -- 保存这些数据
    table.insert(platforms, platformData)
end

-- 创建一个更新颜色的函数
RunService.Heartbeat:Connect(function()
    for _, platform in ipairs(platforms) do
        local isTouched = next(platform.Touches) ~= nil

        -- 对于非激活状态下的平台,快速退出循环
        if not isTouched then
            continue
        end

        -- 检查以前的玩家是否仍然触摸平台
        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
                -- 这个玩家不再接触,将其移除
                platform.Touches[id] = nil
            end
        end

        -- 更新平台的颜色
        if isTouched then
            platform.Part.BrickColor = BrickColor.new("Really red")
        else
            platform.Part.BrickColor = BrickColor.new("Really blue")
        end
    end
end)

希望这能帮助你!祝您好运!

2019-12-26 15:22:07