I am making a game where you collect food to evolve into better creatures, but after a while, the game gets lags spikes when you collect food and i don’t know what to do
the script that i’m using for food collection:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local FoodFolder = ServerStorage:WaitForChild("Food")
local Modules = ReplicatedStorage:WaitForChild("Modules")
local FoodModule = require(Modules:WaitForChild("FoodModule"))
local connection
local function getCorners(part)
local size = part.Size
local cframe = part.CFrame
local halfSize = size / 2
local topRightOffset = Vector3.new(halfSize.X, 0, halfSize.Z)
local topRight = cframe:PointToWorldSpace(topRightOffset)
local bottomLeftOffset = Vector3.new(-halfSize.X, 0, -halfSize.Z)
local bottomLeft = cframe:PointToWorldSpace(bottomLeftOffset)
return topRight, bottomLeft
end
function spawnFood(Food, SpawnArea, ExpGiven, MaxFood, RespawnTime, RequiredLevel)
for i = 1,MaxFood do
wait()
local ClonedFood = Food:Clone()
ClonedFood.Parent = game.Workspace.Foods
ClonedFood.Anchored = true
ClonedFood.Transparency = 0
if SpawnArea == "Grass" then
local spawningPart = game.Workspace["Grass Area"]:WaitForChild("SpawningPart")
local topRight, bottomLeft = getCorners(spawningPart)
local randomX = math.random(math.floor(bottomLeft.X), math.ceil(topRight.X))
local randomZ = math.random(math.floor(bottomLeft.Z), math.ceil(topRight.Z))
ClonedFood.Position = Vector3.new(randomX, game.Workspace["Grass Area"]:WaitForChild("SpawningPart").Position.Y + 8, randomZ)
end
ClonedFood.Touched:Connect(function(Part)
local Character = Part.Parent
local Humanoid = Character:FindFirstChild("Humanoid")
if Humanoid then
local Player = Players:GetPlayerFromCharacter(Character)
if Player then
local leaderstats = Player:FindFirstChild("leaderstats")
local Level = leaderstats:FindFirstChild("Level")
local cooldown = Player:FindFirstChild("Cooldown")
if Level and Level.Value >= RequiredLevel then
if cooldown and not cooldown.Value then
coroutine.wrap(function()
cooldown.Value = true
leaderstats.Exp.Value += ExpGiven
ClonedFood.Audio:Play()
ClonedFood.Transparency = 1
ClonedFood.CanTouch = false
ClonedFood.CanCollide = false
task.wait(1.5)
cooldown.Value = false
task.wait(RespawnTime - 1.5)
ClonedFood.Transparency = 0
ClonedFood.CanTouch = true
ClonedFood.CanCollide = true
end)()
end
end
end
end
end)
end
end
for _, Food in ipairs(FoodFolder:GetChildren()) do
local SpawnArea = FoodModule.GetSpawnArea(Food.Name)
local ExpGiven = FoodModule.GetExpGiven(Food.Name)
local MaxFood = FoodModule.GetMaxFood(Food.Name)
local RespawnTime = FoodModule.GetRespawnTime(Food.Name)
local RequiredLevel = FoodModule.GetLevelRequired(Food.Name)
task.spawn(function()
spawnFood(Food, SpawnArea, ExpGiven, MaxFood, RespawnTime, RequiredLevel)
end)
end
brother, in the spawnfood function you are copying a new model, but you are not destroying them, which means every time you call spawnfood you create a new model and after a while you’ll have thousands of them in workspace which lags the game.
to fix this, when a food is touched, just destroy it. There is no reason why it should be in workspace.
also, use collectionservice, and attributes, this way your spawnfood header would become only food & spawnarea and the rest can be attributes, also you may delete the boolean values.
example of collectionservice with your foods:
--in a random script in serverscriptservice.
--before using this script, add attributes requiredlevel & expgiven to every food.
--give every food part in your game the 'Food' tag.
--to add attributes, scroll down in the properties window on the part and click
-- 'add attribute' -> pick some type & name, and boom.
-- to add a tag, go to properties, all the way down, press + on tags and type 'Food'.
local collectionService = game:GetService("CollectionService")
local function addFood(food: Instance)
if not food:IsA("BasePart") then return end
food.Touched:Connect(function(hit)
local char = hit:FindFirstAnscestoryOfClass("Model")
if not char then return end
local plr = game.Players:GetPlayerFromCharacter(char)
local hum = char:FindFirstChildOfClass("Humanoid")
if not hum or not plr then return end
local lst = plr:FindFirstChild("leaderstats")
if not lst then return end
local level = lst:FindFirstChild("Level")
if not level or level.Value < food:GetAttribute("RequiredLevel") then return end
food.Audio:Play()
food:Destroy()--destroy the food
lst.Exp.Value += food:GetAttribute("ExpGiven")
end)
end
CollectionService:GetInstanceAddedSignal("Food"):Connect(addFood)
for _, f in ipairs(CollectionService:GetTagged("Food")) do addFood(f) end
now, if you want to use your implementation, here is the fix:
--inside touch declaration of spawnfood
--previous code
if cooldown and not cooldown.Value then
cooldown.Value = true
leaderstats.Exp.Value += ExpGiven
ClonedFood.Audio:Play()
ClonedFood:Destroy()
task.wait(1.5)
cooldown.Value = false
end
no, you don’t merge or separate any.
You pick one to use.
the first is a collection and attribute based thing that does the same as your other script.
the second is your implementation with a small change (using :destroy() in the touch handler)
I was going to give you your code with scavenginbot’s fix, but I realize that you intend to reuse the food. I also noticed that you arent actively setting ‘connection’ to any actual events and disconnecting them, but I think the biggest issue is the lack of debounce specifically for the Touched event, not the player. Try this out
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local FoodFolder = ServerStorage:WaitForChild("Food")
local Modules = ReplicatedStorage:WaitForChild("Modules")
local FoodModule = require(Modules:WaitForChild("FoodModule"))
local connection
local function getCorners(part)
local size = part.Size
local cframe = part.CFrame
local halfSize = size / 2
local topRightOffset = Vector3.new(halfSize.X, 0, halfSize.Z)
local topRight = cframe:PointToWorldSpace(topRightOffset)
local bottomLeftOffset = Vector3.new(-halfSize.X, 0, -halfSize.Z)
local bottomLeft = cframe:PointToWorldSpace(bottomLeftOffset)
return topRight, bottomLeft
end
function spawnFood(Food, SpawnArea, ExpGiven, MaxFood, RespawnTime, RequiredLevel)
for i = 1,MaxFood do
wait()
local ClonedFood = Food:Clone()
ClonedFood.Parent = game.Workspace.Foods
ClonedFood.Anchored = true
ClonedFood.Transparency = 0
if SpawnArea == "Grass" then
local spawningPart = game.Workspace["Grass Area"]:WaitForChild("SpawningPart")
local topRight, bottomLeft = getCorners(spawningPart)
local randomX = math.random(math.floor(bottomLeft.X), math.ceil(topRight.X))
local randomZ = math.random(math.floor(bottomLeft.Z), math.ceil(topRight.Z))
ClonedFood.Position = Vector3.new(randomX, game.Workspace["Grass Area"]:WaitForChild("SpawningPart").Position.Y + 8, randomZ)
end
local canEat = true
ClonedFood.Touched:Connect(function(Part)
if not canEat then return end
canEat = false
local Character = Part.Parent
local Humanoid = Character:FindFirstChild("Humanoid")
if Humanoid then
local Player = Players:GetPlayerFromCharacter(Character)
if Player then
local leaderstats = Player:FindFirstChild("leaderstats")
local Level = leaderstats:FindFirstChild("Level")
local cooldown = Player:FindFirstChild("Cooldown")
if Level and Level.Value >= RequiredLevel then
if cooldown and not cooldown.Value then
coroutine.wrap(function()
cooldown.Value = true
leaderstats.Exp.Value += ExpGiven
ClonedFood.Audio:Play()
ClonedFood.Transparency = 1
ClonedFood.CanTouch = false
ClonedFood.CanCollide = false
task.wait(1.5)
cooldown.Value = false
task.wait(RespawnTime - 1.5)
ClonedFood.Transparency = 0
ClonedFood.CanTouch = true
ClonedFood.CanCollide = true
canEat = true
end)()
end
end
end
end
end)
end
end
for _, Food in ipairs(FoodFolder:GetChildren()) do
local SpawnArea = FoodModule.GetSpawnArea(Food.Name)
local ExpGiven = FoodModule.GetExpGiven(Food.Name)
local MaxFood = FoodModule.GetMaxFood(Food.Name)
local RespawnTime = FoodModule.GetRespawnTime(Food.Name)
local RequiredLevel = FoodModule.GetLevelRequired(Food.Name)
task.spawn(function()
spawnFood(Food, SpawnArea, ExpGiven, MaxFood, RespawnTime, RequiredLevel)
end)
end
hey so your code works but there are still lag spikes, i also changed canEat to false only after “if cooldown and not cooldown.Value then” since if it is being touched by like a tree lets say it will not work anymore