Hello! I am pretty new to Roblox Lua but I wanted to make a modular crop registry so eventually I could make some sort of farming game where you could place different types of crops.
My main issue is that it’s using ~1.5 gigabytes when it plants and grows, I am looking for any improvements or ideas on a better way of having tons of crops grow.
I was originally planning on them having their own callback inside themselves to grow after using task.wait until they are fully grown, but I assumed having a global loop for a table to check the grow times would be more optimized. Like I said, very new to Roblox Lua so please tell me if I am doing something wrong and optimized!
If you want a basic rundown I can use this to register a crop in the table:
CropSystem:RegisterCrop(
'Pumpkin',
{
workspace.Models.Pumpkin.PumpkinStage1,
workspace.Models.Pumpkin.PumpkinStage2,
workspace.Models.Pumpkin.PumpkinStage3,
workspace.Models.Pumpkin.PumpkinStage4,
workspace.Models.Pumpkin.PumpkinStage5,
workspace.Models.Pumpkin.PumpkinStage6,
workspace.Models.Pumpkin.PumpkinStage7,
workspace.Models.Pumpkin.PumpkinStage8,
workspace.Models.Pumpkin.PumpkinStage9
},
20,
nil,
true,
1
)
I don’t have much set up but I just made a for loop to just place crops and register them as planted crops:
local spacing = 5
local totalCrops = 500
local cropsPlanted = 0
local rows = math.ceil(math.sqrt(totalCrops))
local columns = math.ceil(totalCrops / rows)
for row = 1, rows do
for col = 1, columns do
if cropsPlanted >= totalCrops then
break
end
local position = Vector3.new(row * spacing, 0, col * spacing)
CropSystem:PlantCrop('Pumpkin', position)
cropsPlanted += 1
if cropsPlanted % math.random(5, 6) == 0 then
task.wait(math.random(0.1 * 10, 0.5 * 10) / 10)
end
end
end
Shared file is below:
local CropSystem = {}
CropSystem.Crops = {}
CropSystem.PlantedCrops = {}
function CropSystem:RegisterCrop(name, models, growTime, harvestTime, removeOnHarvest, cubeSize)
print('Registering crop:', name)
self.Crops[name] = {
Models = models,
GrowTime = growTime,
HarvestTime = harvestTime or 0,
RemoveOnHarvest = removeOnHarvest,
CubeSize = cubeSize,
}
end
function CropSystem:PlantCrop(cropName, position)
print('Planting crop:', cropName, 'at position:', position)
local cropData = self.Crops[cropName]
if not cropData then
warn('Crop not registered:', cropName)
return
end
local cropInstance = Instance.new('Model')
cropInstance.Name = cropName
cropInstance:SetAttribute('Stage', 1)
cropInstance:SetAttribute('GrowthTimeElapsed', 0)
cropInstance.Parent = workspace
local firstStageModel = cropData.Models[1]
for _, child in ipairs(firstStageModel:GetChildren()) do
local clonedChild = child:Clone()
clonedChild.Parent = cropInstance
if clonedChild:IsA('BasePart') then
clonedChild.Anchored = true
end
end
if firstStageModel.PrimaryPart then
local clonedPrimaryPart = firstStageModel.PrimaryPart:Clone()
clonedPrimaryPart.Parent = cropInstance
clonedPrimaryPart.Anchored = true
cropInstance.PrimaryPart = clonedPrimaryPart
else
warn('First stage model does not have a PrimaryPart. Crop placement may fail.')
end
if cropInstance.PrimaryPart then
cropInstance:SetPrimaryPartCFrame(CFrame.new(position))
else
warn('Failed to set PrimaryPart for cropInstance. Cannot set CFrame.')
end
table.insert(self.PlantedCrops, {
Instance = cropInstance,
CropName = cropName,
})
end
function CropSystem:Tick()
for i = #self.PlantedCrops, 1, -1 do
local plantedCrop = self.PlantedCrops[i]
local cropInstance = plantedCrop.Instance
if not cropInstance or not cropInstance.Parent then
table.remove(self.PlantedCrops, i)
continue
end
local cropName = plantedCrop.CropName
local cropData = self.Crops[cropName]
if not cropData then
table.remove(self.PlantedCrops, i)
continue
end
local elapsedTime = cropInstance:GetAttribute('GrowthTimeElapsed') or 0
elapsedTime += 1
cropInstance:SetAttribute('GrowthTimeElapsed', elapsedTime)
local totalStages = #cropData.Models
local stageDuration = cropData.GrowTime / totalStages
local currentStage = math.min(math.floor(elapsedTime / stageDuration) + 1, totalStages)
if cropInstance:GetAttribute('Stage') ~= currentStage then
cropInstance:SetAttribute('Stage', currentStage)
print('Updating crop:', cropName, 'to stage:', currentStage)
local currentPosition = cropInstance.PrimaryPart and cropInstance.PrimaryPart.CFrame or CFrame.new()
cropInstance:ClearAllChildren()
local newModel = cropData.Models[currentStage]
if newModel then
local clonedModel = newModel:Clone()
clonedModel.Parent = cropInstance
if clonedModel.PrimaryPart then
cropInstance.PrimaryPart = clonedModel.PrimaryPart
cropInstance:SetPrimaryPartCFrame(currentPosition)
else
warn('New model does not have a PrimaryPart. Position may not be preserved.')
end
else
warn('Model for stage', currentStage, 'not found for crop:', cropName)
end
end
if elapsedTime >= cropData.GrowTime then
if cropData.RemoveOnHarvest then
print('Crop is ready for harvest or removal:', cropName)
cropInstance:Destroy()
else
-- Handle multiple harvest logic here
end
table.remove(self.PlantedCrops, i)
end
end
end
task.spawn(function()
while true do
CropSystem:Tick()
task.wait(1)
end
end)
return CropSystem