I am making a game like slitherio and whenever the players eat food their snakes gets larger.The problem is that if the snake gets too big it causes a lot of lag
local previouspart = nil
local distance = 2
local numberofballs = 5
local total = numberofballs
local hrp
local char = game.Players.LocalPlayer.Character
local db = true
local limit = 400
local part
local goal
wait()
for i = 1,numberofballs,1 do
part = Instance.new("Part",game.Workspace)
part.Anchored = true
part.Material = Enum.Material.SmoothPlastic
part.Shape = "Ball"
part.BrickColor = BrickColor.random()
part.CanCollide = false
part.Massless = true
--[[local bodyposition = Instance.new("BodyPosition",part)
bodyposition.P = 10000
bodyposition.D = limit
bodyposition.MaxForce = Vector3.new(99999,999999,999999)]]--
hrp = char.HumanoidRootPart
if i == 1 then
part.Position = hrp.Position - hrp.CFrame.LookVector*2
part.Name = "Part1"
else
part.Position = previouspart.Position - previouspart.CFrame.LookVector*distance
part.Name = "Part"..i
end
previouspart = part
wait()
end
spawn(function()
while task.wait() do
for i = 1,numberofballs,1 do
local partfound = game.Workspace:FindFirstChild("Part"..i)
if partfound then
if partfound.Name == "Part1" then
spawn(function()
for x = 0,1,0.01 do
goal = hrp.Position - hrp.CFrame.LookVector*2
partfound.Position = partfound.Position:Lerp(goal,x)
task.wait()
end
end)
elseif partfound ~= nil then
spawn(function()
for x = 0,1,0.005 do
goal = game.Workspace:FindFirstChild("Part"..i-1).Position - game.Workspace:FindFirstChild("Part"..i-1).CFrame.LookVector*Vector3.new(1,0,1)*distance
partfound.Position = partfound.Position:Lerp(goal,x)
task.wait()
end
end)
end
partfound.CFrame = CFrame.new(partfound.Position,hrp.Position)
end
end
end
end)
wait(1)
spawn(function()
while true do
for i, v in pairs(game.Workspace:GetChildren()) do
if game.ReplicatedStorage.food:FindFirstChild(v.Name) then
v.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") and db then
print("length:"..total+1)
db = false
v:Destroy()
part = Instance.new("Part",game.Workspace)
part.Anchored = true
part.Material = Enum.Material.SmoothPlastic
part.Shape = "Ball"
part.BrickColor = BrickColor.random()
part.CanCollide = false
part.Massless = true
part.Position = game.Workspace:FindFirstChild("Part"..numberofballs).Position - game.Workspace:FindFirstChild("Part"..numberofballs).CFrame.LookVector*Vector3.new(1,0,1)*distance
part.Name = "Part"..numberofballs+1
numberofballs += 1
--[[local bodyposition = Instance.new("BodyPosition",part)
bodyposition.P = 10000
bodyposition.D = limit
bodyposition.MaxForce = Vector3.new(99999,999999,999999)--]]
wait(0.1)
db = true
end
end)
end
end
wait()
end
end)
There is an alternative version of your code of how your code can be optimized. But let’s talk about this
for x = 0,1,0.005 do
goal = game.Workspace:FindFirstChild("Part"..i-1).Position - game.Workspace:FindFirstChild("Part"..i-1).CFrame.LookVector*Vector3.new(1,0,1)*distance
partfound.Position = partfound.Position:Lerp(goal,x)
task.wait()
end
The code above can probably cause a lag. Since you are using Lerp for smooth movement of the part. But Lerp function also does calculate distance between 2 points, so you create the loop and lerp it within milliseconds which is really unnecessary. Even that, this loop is place inside another loop. the loop inside spawn has 200 iterations (0,1,0.005) and each of this loop will be multiplied by numberofballs. Let’s say you have 5 balls in you game, that will result in 1,000 iteration in total. Adding numbers for 1,000 times is not heavy, but your method recalculate position for 1,000 times over and over again. Even the loop is inside the spawn which is multi-threaded, it can result in lag at some points.
Alternative version of your code could be try implementing RunService and use Heartbeat for better performance. AlignPosition and AlignOrientation can also be implemented.
You have a lot of loops and loops within loops going on here. One thing that should help you is to not repeatedly loop through all children of game.Workspace and add a touch handler. You are adding a touch handler to the same food parts over and over again like every 1/60th of a second which is a lot of overhead. You should add the touch handler only when that piece of food is created. You might also look up using TAGS to tag something as food so it will set up your generic touch handler the moment you create something and tag it as food.
The best way to implement this is to use attach both AlignPosition and AlignOrientation on each joint of your snake. The first joint will be only one that control direction of your snake. AlignPosition and AlignOrientation in other joints will do the job. I have never implemented this, but I think it is a good approach.
The structure will be like this
AP = AlignPosition
AO = AlignOrientation
First Joint <— AP,AO ---- Second Joint <— AP,AO — Third Joint. And so on.
It is really simple! So basically, Attachment1 will try its best to relocate its position to be close Attachment0. Same thing with AlignOrientation that it will try to relocate the orientation.
Only Attachment1, and Attachment0 are important, you can adjust also adjust speed of that by adjusting MaxForceMaxVelocity, or Responsiveness. Try playing around with those values and see how they affect the movement.
Have you used AlignOrientation yet?, or you can try increasing Responsiveness on each AlignPosition. Too low, your model will fling too much, Too high, your model will fling less, but in an unnatural way. Try finding a sweet spot for the value.