Performance 使用lua和Roblox Studio提高性能
我终于用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
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)