How would you correctly implement object pooling?

the use case here is obvious (bullet hell game, 1000+ parts sometimes, so i don’t want to go through instance-destroy lag)

currently i recycle bullets from and into a storage, and a seperate script modifies it (called ‘index’) which is then returned to the attack modules that asked for the specific bullets from that index

so, whenever a script calls for a bullet, the storage script sends a bullet (not neccesairly default, because I really don’t know if I can return bullets to a default state), where then the index script changes the bullet’s property based on which type was called, which is then sent to the script that called it to then move the bullet.

however, because the index handles everything about the bullet, it is very hard to maintain (adding new types of bullets is insanely tedious as i have to cover all the properties) so I am wondering if I am doing something wrong with object pooling here

another idea I had was to just start off with 1 of each bullet (each bullet has an ID tag) and just clone said unique bullet if there aren’t enough bullets, but i heard clone() is pretty bad so I am not sure if this is a good idea either

You’re going to have to be clearer with your definition of “object pooling.” Do you mean pooling objects into one entity the same way Minecraft does it? Do you mean accessing different types of bullets?

Also, what exactly are you trying to do with this? It’s in a bullet hell game, but what exactly does that entail?

If you want to do object pooling you have to reset the objects at some point. You could define functions that reset the bullets completely when they’re returned to the pool, but some properties might be unnecessary to reset (e.g. position, since a script that uses the bullets is likely to set the bullet position itself, meaning double work is being done). You could even have the calling script be completely responsible for resetting the properties whenever it gets an object, although that’d be pretty tedious as well.

Could you explain your workflow a bit more? Doesn’t seem that tedious

local module = {
	Wisp = function()
		local blast = bulletStorageAPI.getBullet()
		local blastshape = blast:FindFirstChild("Mesh") or Instance.new("SpecialMesh", blast)
		local blastCenter = blast:FindFirstChild("Attachment") or Instance.new("Attachment",blast)
		local blastParticle = blast:FindFirstChild("ParticleEmitter") or blastCenter:FindFirstChild("ParticleEmitter") or Instance.new("ParticleEmitter")
		blastParticle.Parent = blastCenter
		blastParticle.Color = ColorSequence.new(Color3.fromRGB(100,200,255), Color3.fromRGB(20,100,255))
		blastParticle.Size = NumberSequence.new(0.5,0)
		blastParticle.RotSpeed = NumberRange.new(-200,200)
		blastParticle.Transparency = NumberSequence.new(0,1)
		blastParticle.Lifetime = NumberRange.new(0.5,1)
		blastParticle.Speed = NumberRange.new(4,6)
		blastParticle.LockedToPart = true
		blastParticle.Texture = "rbxassetid://4449786143"
		blastParticle.LightEmission = 0.4
		blastParticle.Rate = 100
		blastParticle.ZOffset = -2
		blastParticle.Drag = 0
		blastshape.TextureId = ""
		blastshape.MeshType = Enum.MeshType.Sphere
		blastshape.VertexColor = Vector3.new(1,1,1)
		blastshape.Scale = Vector3.new(1,1,1)
		blast.Transparency = 0.5
		blast.Color = Color3.fromRGB(100,225,255)
		blast.Material = "Neon"
		blast.Size = Vector3.new(1,1,1)
		return blast,blastshape, blastCenter, blastParticle
	end,
	FoxfireDagger = function()
		local blast = bulletStorageAPI.getBullet()
		local blastshape = blast:FindFirstChild("Mesh") or Instance.new("SpecialMesh", blast)
		local blastCenter = blast:FindFirstChild("Attachment") or Instance.new("Attachment")
		local blastParticle = blast:FindFirstChild("ParticleEmitter") or blastCenter:FindFirstChild("ParticleEmitter") or Instance.new("ParticleEmitter")
		blastParticle.Parent = blast
		blastshape.MeshType = Enum.MeshType.FileMesh
		blastshape.MeshId = "rbxassetid://4817006049"
		blastshape.TextureId = "rbxassetid://4449786143"
		blastshape.VertexColor = Vector3.new(0,1,10)
		blastshape.Scale = Vector3.new(1,1,1)
		blast.Size = Vector3.new(1,0.25,4)
		blast.Transparency = 0.6
		blast.Material = Enum.Material.Neon
		blast.CanCollide = false
		blast.Anchored = true
		blastParticle.Texture = "rbxassetid://4449786143"
		blastParticle.Color = ColorSequence.new(Color3.fromRGB(60,200,255), Color3.fromRGB(0,60,255))
		blastParticle.RotSpeed = NumberRange.new(-200,200)
		blastParticle.Transparency = NumberSequence.new(0,1)
		blastParticle.Size = NumberSequence.new(0.15,0)
		blastParticle.Speed = NumberRange.new(0)
		blastParticle.Lifetime = NumberRange.new(0.1,1.5)
		blastParticle.Rate = 100
		blastParticle.LightEmission = 0.5
		blastParticle.ZOffset = 0
		blastParticle.LockedToPart = false
		blastParticle.Drag = 0
		return blast, blastshape, blastParticle
	end,
	GenericBullet = function()
		local blast = bulletStorageAPI.getBullet()
		local blastshape = blast:FindFirstChild("Mesh") or Instance.new("SpecialMesh", blast)
		local blastCenter = blast:FindFirstChild("Attachment") or Instance.new("Attachment",blast)
		local blastParticle = blast:FindFirstChild("ParticleEmitter") or blastCenter:FindFirstChild("ParticleEmitter") or Instance.new("ParticleEmitter")
		blastParticle.Parent = blastCenter
		blastParticle.Enabled = false
		blastshape.TextureId = ""
		blastshape.MeshType = Enum.MeshType.Sphere
		blastshape.VertexColor = Vector3.new(1,1,1)
		blastshape.Scale = Vector3.new(1,1,1)
		blast.Transparency = 0.5
		blast.Color = Color3.fromRGB(255,255,255)
		blast.Material = "Neon"
		blast.Size = Vector3.new(1,1,1)
		return blast
	end
}

this is the index so far
i meant ‘tedious’ as it is fairly easy to forget one or two properties of an object and then the entire bullet is now changed - and then it becomes hard to even figure out which property i had missed, etc, etc. It’s also going to be a problem, say, if i want to add trails in the future because then every bullet that doesn’t need trails would have to manually disable the trails, and in the future adding new things would result in combing through a lot of different bullets

although, i might consider having a baseline bullet and have the script that recycles the bullets return them manually

1 Like

Woah, yeah I see what you mean. Sorry, I’ve got no good ideas for making it less tedious :confused:

PartCache does object pooling, maybe it can work for you?

I’ve found it in the past, forgot the name, and was recently reminded about it from @boatbomber