What is the best way to “connect” two parts without causing a memory leak?

What is the best way to “connect” two parts without causing a memory leak?

I am trying to make a fire propagation system which spreads fire from one part to nearby parts. Right now, the system is set up in an OOP manner. Here is some psuedocode that shows how my system is set up:

local parts = {}
local partInfo = { ["FireSize"] = 0, ["ConnectedParts"] = {}}

parts[game.Workspace.Part] = copyTable(partInfo)

After looping through every part and setting up the partInfo table, I use Workspace:FindPartsInRegion3 for each part to find nearby parts and add them to the ConnectedParts table. However, after reading stravant’s article about memory leaks, I am worried that I am causing a memory leak. Here is the section that worries me.

do -- OOPS!... still leaking, it doesn't have to be a direct reference!
    local p = Instance.new('Part')
    local dataTable = {Message = "Test"; Part = p}
    p.Touched:connect(function() print(dataTable.message) end)
end

Am I causing a memory leak? If so, what is the best way to store nearby parts for each part? I am aware that I could use Workspace:FindPartsInRegion3 each time I need to reference nearby parts, but it is much faster to run that only once.

3 Likes

Ahh man, I love it when I get to work on something I wanted to work before I actually start work on it. :smiley:

Fire propagation (which I’ve never handled before) works on data. Not a lot of it. But specific to the instance on fire, and the instance to be on fire. Like how wet is this instance? Is it hot enough and dry enough to catch on fire? How close is the fire to this instance? How intensely is the fire burning? All of these things increase the chance to propagate.

In my case I’d simplly tag an instance as on fire. And then let a script check for parts within x radius. Maybe a slowly increasing Region3 until it reaches the fires maximum potential and intensity. In which any part found inside of the region which can burn, and is currently heating up, or drying out would catch fire and propagate.

Meanwhile after x amount of time I’d either char the original instance that’s on fire, add a smoke effect, and add it to debris if you wanted to delete old instances that burned up.

I want to add some sort of system like this for my boats. This is all theory based on how I would handle it though.

1 Like

Hi T0ny, thanks for the reply! I’ve actually already finished one version of this fire propagation system. Right now I am just trying to optimize it and this is where I’ve gotten stuck. If I have thousands of parts in a model that is “on fire”, how do I efficiently update each relevant part? Casting a 1000 Region3’s around each part every 10th or 100th of a second is quite clearly not the answer. That why I hoped to cast the Region3 only once at the beginning and then build an array for each part of the surround parts that might affect it. However, this is where I was running into what I believe is a memory leak error. I have 40 MB of untracked memory on the server when running my current system. Do you think this is due to the table of surrounding parts that I have for each part?

1 Like

By taking use of the collection service you can greatly reduce the number of parts you actually are iterating on since only the instances that are tagged “on fire” would be casting Region3s. Also you should literally set a max number of parts that are allowed to be on fire, as well as propagating. For instance, propagation doesn’t need to occur when every part that was hit in a Region3 (that has a tag that says the part can burn) is on fire… obviously a Region3 no longer need to be casted since there are no more parts that can catch on fire (obviously anything that touches something that is on fire can catch on fire, including the player but that’s a separate system).

Once the max number of parts that are able to be on fire is on fire you should start “burning out” other parts that were on fire. (You do have a maximum limit to the number of particles that can be rendered)

This will help optimization quite a bit. In real life, a single ember can travel miles (so I heard.) This just means your Region3 is bigger. Plus Region3s let you set a max number of parts to return. So there’s lots of room here for optimization.

As I was recently made aware from @XAXA if you use an index map you can efficiently loop through the instance table returned by CollectionService:GetTagged(). By using tags, the amount of code is only executed on specific instances.

If you want, you can even batch propagation. Meaning after a specific number of seconds, a propagation wave is ran and anything that can propagate will propagate. This will give plenty of downtime in between to keep from bogging the thread. Let alone, you can run it in another thread as well. And I’m sure you’ll be able to find even more opportunities to optimize it even further.

I think I’m on the right path as I already have the ideas you implemented! I use collection service, but only to display particles client side. In my experience, rapid use of collection service has proven laggy. I wish I kept a screenshot of the microprofiler while I was still using only tags, but you could see in how much time the collection service took up while implementing it. Since I have multiple fire running at the same time, using CollectionService:GetTagged() actually iterates through more parts than if I just iterated through every part in each individual fire. And, using CollectionService:HasTag() for each part in my fire is also much slower. Also, I am already using batch propagation! Although, currently I have each fire propagating at the same time. I’m thinking about offsetting them to prevent spikes. Really, all I’m trying to figure out is if the best way to store information about parts and iterate through them is through a table, or if there is a better way. It is comforting to know that I’ve been on the right track though!

1 Like