I have a script that is creating thousands of coroutines to handle animation on thousands of tentacles. The rate for this script is getting unbelievably high! How can I improve my script performance?
This is my current code:
local function Animate(rig)
local anim = script.TentacleAnim
local animator = rig.AnimationController
local playerDetectionRange = 500
local playing = false
local function isPlayerNearby()
local players = game:GetService("Players"):GetPlayers()
for _, player in ipairs(players) do
local character = player.Character
if character then
local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
if humanoidRootPart and (script.Parent.Tentacle.Position - humanoidRootPart.Position).Magnitude <= playerDetectionRange then
return true
end
end
end
return false
end
while task.wait(1) do
if isPlayerNearby() and playing == false then
playing = true
local animation = animator:LoadAnimation(anim)
animation.Looped = false
animation:Play()
animation.Ended:Wait()
end
end
end
script.Parent.ChildAdded:Connect(function(child)
if child:IsA("ProximityPrompt") then
print("proximityPrompts")
elseif child:FindFirstChild("Tentacles") then
local tentacles = child.Tentacles:GetChildren()
for _, tentacle in pairs(tentacles) do
coroutine.wrap(Animate)(tentacle)
end
end
end)
You should put constant values or functions outside the animate function because it creates a new function/variable everytime you call it which is unnecessary and wastes performance/memory.
Ah! Great idea. I can’t believe I didn’t take the isPlayerNearby() function out. I dont know if this will take the performance down enough though. It’s still climbing into the thousands very quickly.
local counter = 0
game:getService("runservice").Heartbeat:connect(function(deltaTime)
Counter += deltaTime
If counter >= 1 then -- one is the cooldown time and can be replaced if wanted.
-- run animation
Counter = 0
End
local playerDetectionRange = 500
local function isPlayerNearby(tentacle)
local players = game:GetService("Players"):GetPlayers()
for _, player in ipairs(players) do
local character = player.Character
if character then
local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
if humanoidRootPart and (tentacle.TentacleRig.Position - humanoidRootPart.Position).Magnitude <= playerDetectionRange then
return true
end
end
end
return false
end
local function Animate(rig)
local anim = script.TentacleAnim
local animator = rig.AnimationController
local playing = false
local counter = 0
game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
counter += deltaTime
if counter >= 1 then
if isPlayerNearby(rig) and playing == false then
playing = true
local animation = animator:LoadAnimation(anim)
animation.Looped = false
animation:Play()
animation.Ended:Wait()
end
end
counter = 0
end)
end
script.Parent.ChildAdded:Connect(function(child)
if child:IsA("ProximityPrompt") then
print("proximityPrompts")
elseif child:FindFirstChild("Tentacles") then
local tentacles = child.Tentacles:GetChildren()
for _, tentacle in pairs(tentacles) do
coroutine.wrap(Animate)(tentacle)
end
end
end)
EDIT: I fixed it by adding the local counter = 0 inside the if statement.
The script rate is too high mostly because you’re doing too much infinite loops, so it is going to make the game super laggy and crash.
You should do only one loop that handle all tentacles in coroutines.
Something like this
game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
for _, Child in pairs(script.Parent:GetChildren()) do
if Child:FindFirstChild("Tentacles") then
local tentacles = child.Tentacles:GetChildren()
coroutine.wrap(Animate)(tentacles)
end
end
end)
You have to remake the function, probably using a table to check each tentacle status, here is an exemple:
local TentaclesTable = {}
local function Animate(rig)
local anim = script.TentacleAnim
local animator = rig.AnimationController
if not TentaclesTable[rig] then
TentaclesTable[rig].playing = false
end
if isPlayerNearby(rig) and TentaclesTable[rig].playing == false then
TentaclesTable[rig].playing == true
local animation = animator:LoadAnimation(anim)
animation.Looped = false
animation:Play()
animation.Ended:Wait()
TentaclesTable[rig].playing == false
end
end
Mmm…if it’s truly okay with you,go for it. But otherwise,I think if you have script problems,there must be a way to shorten it for you to find the problem easier.