Component Service
The ComponentService binds Roblox CollectionService tags to Luau component classes. When a tagged instance appears, a component object is created; when the tag is removed or the instance is destroyed, the component is cleaned up.
Access via Riptide.ComponentService.
type ComponentClass = { new: (instance: Instance) -> any, Destroy: ((self: any) -> ())?,}
type ComponentServiceAPI = { Get: (self, instance: Instance, tagName: string?) -> any?, UnregisterTag: (self, tagName: string) -> (),}Component Contract
Section titled “Component Contract”A component is a ModuleScript placed inside the ComponentsFolder. Its filename must match the CollectionService tag name.
Every component must return a table with:
| Field | Required | Signature | Description |
|---|---|---|---|
new | ✅ | (instance: Instance) -> self | Constructor. Called when a tagged instance is detected. |
Destroy | ❌ | (self) -> () | Cleanup. Called when tag is removed or instance is destroyed. |
Example — Lava.lua
Section titled “Example — Lava.lua”local Lava = {}Lava.__index = Lava
function Lava.new(instance: BasePart) local self = setmetatable({ _instance = instance, _connection = nil :: RBXScriptConnection?, }, Lava)
self._connection = instance.Touched:Connect(function(hit) local humanoid = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if humanoid then (humanoid :: Humanoid):TakeDamage(10) end end)
return selfend
function Lava:Destroy() if self._connection then self._connection:Disconnect() self._connection = nil endend
return LavaTag any BasePart with "Lava" in Studio or via CollectionService:AddTag() — the component will be instantiated automatically.
Methods
Section titled “Methods”ComponentService:Get(instance: Instance, tagName: string?) -> any?Retrieves the component object attached to an instance.
With tag name — returns the specific component:
local lava = Riptide.ComponentService:Get(part, "Lava")if lava then print("This part has a Lava component")endWithout tag name — returns the component only when exactly one is attached:
local component = Riptide.ComponentService:Get(part)UnregisterTag
Section titled “UnregisterTag”ComponentService:UnregisterTag(tagName: string) -> ()Disconnects all CollectionService listeners for a specific tag and destroys all active component instances of that tag.
Riptide.ComponentService:UnregisterTag("Lava")This is useful for hot-reload or test teardown scenarios.
ComponentService is started automatically when you pass ComponentsFolder in your Launch config:
Riptide.Server.Launch({ ModulesFolder = ServerScriptService.Services, ComponentsFolder = ReplicatedStorage.Components, -- ← enables ComponentService})The service scans all ModuleScript descendants in the folder, requires each one, and:
- Validates the component has a
newconstructor. - Connects to
CollectionService:GetInstanceAddedSignal(tagName)andGetInstanceRemovedSignal(tagName). - Processes all already-tagged instances immediately.
Memory Management
Section titled “Memory Management”ComponentService uses weak-key tables (__mode = "k") for its internal registry. This means:
- When an instance is garbage collected, its registry entry is automatically freed.
- On
Instance.Destroying, the component’sDestroy()method is called and all connections are cleaned up. - On tag removal,
CleanupComponentis triggered to tear down the component and disconnect theDestroyinglistener.
This ensures zero memory leaks even under heavy instance churn.