我终于使用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和trying制作游戏非常陌生,所以我真的不知道如何提高性能。滞后变得越来越糟的事实似乎表明记忆没有得到有效释放?我以为这是自动发生的。无论如何,任何帮助都将不胜感激。
较小更改-循环制作新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)
我希望这会有所帮助!祝你好运!