PartCache, for all your quick part-creation needs

It might be more performant to disable CanQuery, CanCollide, CanTouch and CastShadow for cached parts. I have not tested this, but maybe this works.

1 Like

is this better than debris service?

1 Like

Short and simple: Yes.
CFrame works best.

1 Like

Sorry for the bump, but oh wow. This module is simple yet soooo effective. It made my part rain script run waaaay much efficiently. I can now have over 300 moving rain parts on screen with maximum performance!

2 Likes

Just found this bug (it will never reach the assertwarn function call if it is == 0):


I’m trying to make it 0 parts big so it will auto fill up as needed. I don’t want to start with a value which seems sort of arbitrary. Is it better to start with a super small value and let it fill up automatically or have some random large number so you never have to worry about auto fill but possibly have excess parts. I would really prefer the former.

2 Likes

I don't know what I'm doing wrong here but, Apparently parenting objects is alot faster than this module.

Here's my code:
local camera = workspace.CurrentCamera
local altitude = 78

local tweenService = game:GetService("TweenService")
local replicatedStorage = game:GetService("ReplicatedStorage")

local partCache = require(replicatedStorage:WaitForChild("Modules"):WaitForChild("PartCache"))

local F_prefabs = replicatedStorage:WaitForChild("Prefabs")
local PF_ambience = F_prefabs:WaitForChild("Ambience")

local P_rainDrop = partCache.new(PF_ambience:WaitForChild("RainDrop"), 1, camera)

local function newDrop(position)
	coroutine.wrap(function()
		wait(math.random())

		local rainDrop = P_rainDrop:GetPart()
		rainDrop.Position = position
		rainDrop.Beam.Enabled = true
		rainDrop.Ripple.WaterRipple0.Size = UDim2.new(0,0,0,0)
		rainDrop.Ripple.WaterRipple1.Size = UDim2.new(0,0,0,0)
		rainDrop.Ripple.WaterRipple1.UIStroke.Thickness = 10
		rainDrop.Ripple.WaterRipple1.UIStroke.Transparency = 0.7
		rainDrop.Ripple.WaterRipple0.Transparency = 0.5
		
		local RCP_physics = RaycastParams.new()
		RCP_physics.FilterDescendantsInstances = {camera}
		local RC_physics = workspace:Raycast(position, Vector3.new(0, -5000, 0), RCP_physics)

		if RC_physics then

			local tweenTime = ((RC_physics.Position - position).Magnitude/270)

			local animation = tweenService:Create(rainDrop, TweenInfo.new(tweenTime, Enum.EasingStyle.Linear), {Position = RC_physics.Position})

			animation:Play()
			animation.Completed:Wait()
			rainDrop.Attachment1.Splash:Emit(50)
			rainDrop.Beam.Enabled = false

			local T_waterRipple0 = tweenService:Create(rainDrop.Ripple.WaterRipple0, TweenInfo.new(0.3, Enum.EasingStyle.Linear), {
				Size = UDim2.fromOffset(150,150);
				Transparency = 1
			})
			local T_waterRipple1 = tweenService:Create(rainDrop.Ripple.WaterRipple1, TweenInfo.new(0.4, Enum.EasingStyle.Linear), {
				Size = UDim2.fromOffset(130,130);
			})
			local T_waterRipple1Stroke = tweenService:Create(rainDrop.Ripple.WaterRipple1.UIStroke, TweenInfo.new(0.4, Enum.EasingStyle.Linear), {
				Transparency = 1;
				Thickness = 0;
			})

			T_waterRipple0:Play()
			T_waterRipple1:Play()
			T_waterRipple1Stroke:Play()
			wait(1)
			P_rainDrop:ReturnPart(rainDrop)
		end
	end)()
end

while wait() do
	
	coroutine.wrap(function()
		local seed = math.random()

		for x = -30, 30, 15 do
			for z = -30, 30, 15 do

				local basePosition = Vector3.new(camera.CFrame.Position.X, altitude, camera.CFrame.Position.Z)

				local x_noise = math.noise(x/15,z/15,seed)
				local z_noise = math.noise(z/15,x/15,seed)

				local position = basePosition + Vector3.new(x, 0, z) + (Vector3.new(x_noise, 0, z_noise) * 16)

				newDrop(position)

			end
		end
	end)()
	
end
2 Likes

Im using CFrames to actually and FINALLY make Occlusion Culling a real thing. Initially i thought reparenting is the best option but i guess im wrong.

Now this is how it works, I’ll be using Camera: WorldToScreenPoint() to check if the player can see the parts/models or not. If they can they will stay at their original position, if not they will be CFramed away.

Thank you @Xan_TheDragon for letting me realize this as a solution.\

The problem is bringing the models/parts back, thought of replacing those with invisible parts.

2 Likes

Man I’ve been looking for this for a week only to click the link and realise I had already gotten the module. :sweat_smile:

3 Likes

Is this still the case? ||char||

So does that mean we don’t have to use PartCache because its already in the FastCast module?

I have found this error:

image

I can see that it isn’t a red underline, meaning it isn’t an error and just roblox being roblox.

1 Like

Is it possible to use this even if the bullets are all client sided? So I would have to use it on the localscript, and is it also possible if I could use it to also delete impact parts?

How does this deal with cases where a part from part cache gets destroyed, or properties of a part in the cache change? When getting that part again, it won’t be the same as the template part anymore.

1 Like

It doesn’t. If it happens to pick the altered part, then all alterations will still be there. If you destroy the part, it will not be removed (and by extension, if it is in the available list, GetPart may return the destroyed reference.)

Hello!

This is the first time im trying to use modulescripts and im having a hard time understanding how it works.

I wrote this line of code that i think should spawn a part.
local danmaku = PC:new(BType.bullet3,1,workspace.Projectiles)
But it gives an error saying that the modulescript is trying to compare a number to nil.
I’ve looked inside the modulescript and the error is caused by this line.
assert(numPrecreatedParts > 0, "PrecreatedParts can not be negative!")
I’ve tried deleting it, but it just makes a chain reaction where more and more errors appear.

Can anyone tell me what im doing wrong here?

edit:I got everthing working except for 1 part… is there any way to replicate a debris using returnpart?

That sounds like a significant problem to me.

1 Like

Heya, I have a question about the module.

Say if there are multiple players in the game and they’re all shooting at the same time, while all bullets are client-sided, do I need to create a new cache with a bunch of parts for each player or could there be another way? Thanks for reading :slight_smile:

Also I noticed that the FPS still drops even though the bullets are cached…

1 Like

Hi, I’ve been using your Module in combination with FastCast for some time now, and I’ve noticed a small problem. Sometimes, the created cosmetic parts are not deleted properly, and they keep floating in the world. This is probably due to server lag or whatever, and that’s fine. How do I remove these though? Clearing the cosmetic parts map doesn’t work properly -as it causes current used guns to not show any cosmetic bullets anymore- and I can’t use :Dispose, as the provider that was used to create them is long deleted.

So, any way to properly remove old cosmetic bullets and let new bullets be created using the MakeFromTemplate function?

I figured out how this happens btw; it’s when the entire tool (and thus script) is destroyed, but the cosmetic bullets are not removed. Any quick solution for that?

@Xan_TheDragon

I have fixed this myself for now, by firing an event every time I destroy the tool harbouring the cache. Maybe there’s an automatic way to implement this in the cache, so I’ll leave my previous comments.

I’ve run into bug where if I shoot my bullet you can see bullet’s trail going from the sky and when the bullet lands you can also see that the trail goes into the sky
I tried enabling and disabling the trail but it didn’t give me any results :frowning:

oh and here’s my script


local function onRayHit(cast, raycastResult, segmentVelocity, bullet)
	local hitPart = raycastResult.Instance
	local hitPoint = raycastResult.Position
	local normal = raycastResult.Normal	
	

	local hit = hitPart ~= nil and hitPart.Parent ~= nil
	if hit then
		local humanoid = hitPart.Parent:FindFirstChildOfClass("Humanoid") -- Is there a humanoid?
		
		delay(.01, function()
			bullet.tracer.Parent = nil
			print("falsed yo mama")
			wait(2)
			bulletCache:ReturnPart(bullet)
		end)
	end
end