Example, im making a tycoon, and so far i have at least two planned things i want to use it #1 being the droppers, pull from here, edit properties, drop, once drop is collected send back #2 a collect effect that needs a certain type to edit and use, and then put back
For anyone who’s thinking of using PartCache, it’s excellent!
But please, make sure to change the CFrame position it comes with because Roblox has an engine bug that can cause your maps to flicker. This only happened to our team in areas where PartCache was used at a Y axis of >100, why? I have no idea.
Some severe bug within the engine is causing this all and Roblox does not seem to do well with parts that are positioned so far away.
Hello! Does this module work with StreamingEnabled? I’ve been tweaking my game to enable StreamingEnabled for performance purposes but my script using this module doesn’t seem to be working properly, i have it set so 10 bullets should be created on startup, but that doesnt seem to be working, instead bullets are only created when shot out.
local bullet = RP.Misc:WaitForChild("Bullet")
cache = PartCacheModule.new(bullet, 10)
cache:SetCacheParent(workspace:WaitForChild("Bullets"))
I’ve noticed the expansion part of the code works properly when more than 10 bullets are created, so it seems everything else is working properly other than the initial creation of parts
Sorry for the double reply but i managed to fix the issue by making a small tweak to the PartCache script, i made it so bullets were created in a closer position to the player’s spawn under the map and then moved them back towards the storage area after a wait()
local function MakeFromTemplate(template: BasePart, currentCacheParent: Instance): BasePart
local part: BasePart = template:Clone()
-- ^ Ignore W000 type mismatch between Instance and BasePart. False alert.
part.CFrame = CFrame.new(0, 0, 0) --modified from part.CFrame = CF_REALLY_FAR_AWAY
part.Anchored = true
part.Parent = currentCacheParent
return part
end
function PartCacheStatic.new(template: BasePart, numPrecreatedParts: number?, currentCacheParent: Instance?): PartCache
...
for _ = 1, newNumPrecreatedParts do
local part = MakeFromTemplate(template, object.CurrentCacheParent)
wait()
part.CFrame = CF_REALLY_FAR_AWAY
table.insert(object.Open, part)
end
...
function PartCacheStatic:GetPart(): BasePart
...
if #self.Open == 0 then
warn("No parts available in the cache! Creating [" .. self.ExpansionSize .. "] new part instance(s) - this amount can be edited by changing the ExpansionSize property of the PartCache instance... (This cache now contains a grand total of " .. tostring(#self.Open + #self.InUse + self.ExpansionSize) .. " parts.)")
for i = 1, self.ExpansionSize, 1 do
local part = MakeFromTemplate(self.Template, self.CurrentCacheParent)
wait()
part.CFrame = CF_REALLY_FAR_AWAY
table.insert(self.Open, part)
end
end
...
Not sure if this is the cleanest solution but hopefully it helps anyone having a similar issue
Can you add in a new function named PCache:GetAvailableParts() or PCache:GetUsingParts(), or even PCache:GetPreCreatedPart()? I am trying to detect when there are no using parts, so that when the ReturnPart() function is called, i can check whether it is the last one to delete the part cache. Basically, i am using FastCast, but i encountered a problem in which the bullets completely disappear. My most recent solution is to create a new partcache with a relatively low precreated part amount, then dispose it once all bullets has been returned.
Putting this here for anyone else who gets this issue:
Sometimes when you return parts to their cache, the shadows glitch and flash off an back on. This is undesirable especially if you’re returning a bunch of parts frequently.
To resolve this just go in the module and change the huge CFrame constant to something smaller. I did 1e7
.CFrame do be taking performances however it is only possible to notify at around thousands of parts, which lets be real will probably not happen in a single frame often, but if you somehow manage to get conditions like this, i’m pretty sure you can use something called workspace:BulkMoveTo(partList, cframeList)
basically it allows you to update more parts cframes in a single frame way faster, here we could kinda get every moved part in the frame, then use bulkmoveto to move all of them at once, which could probably make performances better?
It seems just setting Anchored = true alone is not enough, otherwise the cached part retains the velocity data and when re-summoned it will be moving at the old velocity as soon as it is unanchored.
how would i refill the cache if a cache part gets destroyed?
im using part cache for debris, but if the debris falls into the void and gets destroyed, i dont think the part cache refills itself, as the part isnt being returned. how do i refill the cache?
I noticed there is a very minor error in PartCacheStatic.new definition.
You use:
local newNumPrecreatedParts: number = numPrecreatedParts or 5
to deal with the possibility of getting a nil argument for numPrecreatedParts, but then two lines later you
assert(numPrecreatedParts > 0, “PrecreatedParts can not be negative!”)
assertwarn(numPrecreatedParts ~= 0, “PrecreatedParts is 0! This may have adverse effects when initially using the cache.”)
Whilst this still works, it is responsible for some of the type def warnings (using a relational operator against a nil), I changed the function to this:
function PartCacheStatic.new(template: BasePart, _numPrecreatedParts: number?, currentCacheParent: Instance?): PartCache
local numPrecreatedParts: number = _numPrecreatedParts or 5
local newCurrentCacheParent: Instance = currentCacheParent or workspace
assert(numPrecreatedParts > 0, "PrecreatedParts can not be negative!")
assertwarn(numPrecreatedParts ~= 0, "PrecreatedParts is 0! This may have adverse effects when initially using the cache.")
assertwarn(template.Archivable, "The template's Archivable property has been set to false, which prevents it from being cloned. It will temporarily be set to true.")
local oldArchivable = template.Archivable
template.Archivable = true
local newTemplate: BasePart = template:Clone()
template.Archivable = oldArchivable
template = newTemplate
local object: PartCache = {
Open = {},
InUse = {},
CurrentCacheParent = newCurrentCacheParent,
Template = template,
ExpansionSize = 10
}
setmetatable(object, PartCacheStatic)
for _ = 1, numPrecreatedParts do
table.insert(object.Open, MakeFromTemplate(template, object.CurrentCacheParent))
end
object.Template.Parent = nil
return object
-- ^ Ignore mismatch here too
end
I think the metatable type warning for the return object is unavoidable.
Is PivotTo() faster than directly changing the CFrame? I understand that it doesn’t fire property changed events, but are we sure there isn’t some other overhead?
PivotTo() is basically .CFrame but mostly used for models or objects with a different pivot. PivotTo is just meant to replace SetPrimaryPartCFrame.
I have seen in multiple posts that they are around the same speed as they both update the geometry in the same way kinda (and from an entity systems i have used back then with 2k enemies basically around 14000~16000 parts, pivotto wasn’t any different than .CFrame).
1 thing which is more efficient however is workspace:BulkMoveTo(), which is the best in therm of performance, but you should only use it when you have to move a lot of parts in the same frame (reason why it is called BulkMoveTo), else it kinda becomes useless
i don’t really think it will be of any use for part cache however