使用 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)
希望对您有所帮助!祝你好运!
我终于使用 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)
希望对您有所帮助!祝你好运!