Destroying a script will suspend its threads (coroutines), breaking my logic

I have several modules which will spawn threads (such as a timer module); however, these threads are completely killed suspended whenever a calling script is destroyed (only threads which were created within that destroyed script are killed suspended). This breaks my logic completely – for example, let’s say there is a zombie with a script under it which applies a combat tag to any humanoid that it touches, which creates a timer from the timer module, which creates a new thread to clean up said tag. If the zombie is destroyed (from sources like being cleaned up after death), and the thread to destroy the tag hasn’t already been resumed, the thread will be killed suspended, and the tag will not be properly cleaned up. This will result in ever-increasing memory (all tags are stored in a table, and removed when cleaned up), and inaccurate sources of death.

This is quite important to my game, and I’d like some insight on possible solutions. Thanks for the help.

You could use .Destroyed and connect a new thread there to remove all items that could cause memory leaks, however I would just move this logic outside of the physical zombie model (a centralized script controlling all zombies in serverscriptservice?).

The best thing I can think of is removing your tag creation from your zombie scripts entirely and putting it into its own standalone script, then make a bindable event that allows your zombie scripts to request a tag to be made by the standalone script. As the zombie script didn’t make the tag even if it is destroyed it won’t break.

My biggest gripe with this solution is that the timer module is not limited to zombies; there is another module that creates humanoidEffects (like fire, healing, ragdoll, stun, etc), but uses the same timer module, and also creates it’s own threads for looping functions, etc. They are called from tools, which also get destroyed. I’d have to centralize a hefty amount of scripts. It’s not a bad solution, but it’s definitely a bit of work.

Sort of the same idea, but bindables tend to be slow in some circumstances. Their overall behavior is unpredictable as well; you can’t really tell when or if they’re going to throttle (sort of like the legacy wait() function). Also, as much as i’d like to make a centralized script to keep consistency, there is just a lot of work to be done in those areas.

If there is really nothing else i can do though, I’ll probably have to work with one of these solutions.

How are you tagging these combat humanoids and effects?

Effects should probably utilize debris service and tagging could be switched to CollectionService or even Attributes.

Humanoids are determined to be actual humanoids when they have a Character class object (another module). Npcs such as zombies are assigned the Npc subclass object of Character, and players are simply assigned to the Character class.

At this point, now the Character can be recognized by the combat module, and the effect module. Both tags and effects are their own class objects with their own methods which is why I can’t use CollectionService or Instances and Debris.

I specifically designed these modules to be easily accessible through all scripts, but it definitely becomes a problem when the modules cannot control the environment in which their methods are called in.

I’m wondering if there’s some sort of proxy i can make (not involving BindableEvents) which can run a thread separate to the script. If anyone has ideas, please go ahead and share

The above solutions seem more like band-aids for a serious issue that revolves around my game. Modulating every single script which calls a method which invokes a new thread doesn’t seem like a good solution for me right now.

This bug has prevented me from continuing my work as I cannot find a proper solution to this seemingly trivial problem. Even if I modulated every script which uses these modules, I imagine that there could still be unexpected/inconsistent behavior through edge cases unbeknownst to me.