Implementing CollectionService

Recently, I’ve been looking for ways to easily implement behavior using the CollectionService in conjuction with the tag editor plugin. I would like to share my method, but I want to make sure there’s not something I’m over-looking. It’s meant to be as simple as possible; with the least amount of redundant code.

Basically, I create a folder on the client and/or server, depending on where I want the behavior implemented. The only requirement is that the container be able to run a script within the desired enviroment, eg server or client. The name of this folder is irrelevant, but I usually name it Collections, Behaviors, or the like.

I then add the following script. Be sure to use the appropriate type, either Script or LocalScript, depending on context. The name isn’t important, but I name mine ChildAdded for clarity.

local CollectionService = game:GetService("CollectionService")

local function addCollection(module)
	-- Only accept module scripts
	if not module:IsA("ModuleScript") then return end
	
	-- Import the module
	local collection = require(module)
	
	-- Check requirements
	assert(type(collection.Create) == "function", module.Name.." is missing create function.")
	assert(type(collection.Destroy) == "function", module.Name.." is missing destroy function.")
	
	-- Bind create function to added signal
	CollectionService:GetInstanceAddedSignal(module.Name):Connect(collection.Create)
	
	-- Bind destroy function to removed signal
	CollectionService:GetInstanceRemovedSignal(module.Name):Connect(collection.Destroy)
	
	-- Create collections that may already be added
	for _, part in next, CollectionService:GetTagged(module.Name) do collection.Create(part) end
end

-- Add collection when a module is added to parent folder
script.Parent.ChildAdded:Connect(addCollection)

-- Add collections already loaded
for _, child in next, script.Parent:GetChildren() do coroutine.resume(coroutine.create(addCollection), child) end

This script looks and listens for modules added to it’s parent folder. My current implementation expects the ModuleScript to return a simple object containing two methods: Create() and Destroy(). Both functions receive exactly one argument, the instance being tagged by the CollectionService.

Below is the ModuleScript I use as a template. The Instance.Name of the module MUST coincide with the tagName given to the tagged instance.

local Collection = {}

function Collection.Create(part)
	print("InstanceAdded", script.Name)
end

function Collection.Destroy(part)
	print("InstanceRemoved", script.Name)
end

return Collection

The file structure would look something like this when done:

  • ServerScriptService
    • Folder “Collections”
      • Script “ChildAdded” - The first script used to load the modules.
      • ModuleScript “KillBrick”
      • ModuleScript “JumpPad”

That would suggest we have two tags added to the tag editor: KillBrick and JumpPad. The actual code to implement such a feature would be up to you.

So what do you think? Do you have any suggestions? Would you use such a system? How could I better explain my method? And if I were to post this, would you consider it a resource or tutorial?

Thanks in advance for your time.

Not sure why you would want to use coroutines here, but I guess that you can. Also, is next a thing? The code looks fine overall.

Maybe you find the Knit framework interesting. It comes with a Component object that basically uses the CollectionService in a similar way that you do.

I use the coroutines in case the module uses a yielding function. next, tbl is a long form of ipairs, with slightly better performance.

I’ll take a look at that library, thanks for the reference.