Mechanic
This was deprecated in v1.0.0
Deprecated
Mechanic is no longer maintained and is kept only for existing projects. Use Binder instead; it covers the same use case with a smaller API.
Mechanic attaches behaviour to every instance that carries a CollectionService tag. It wraps
CollectionService:GetInstanceAddedSignal / GetInstanceRemovedSignal and filters the tagged
instances by class name, by ancestor, or with a custom predicate. Every instance that passes
the filters gets an AppliedMechanic object holding its own per-instance
Data table and a Trove that is cleaned when
the instance is untagged, destroyed, or moved out of the allowed ancestors.
The module returns a table with three constructors: new, newConstructor and bindToClass.
Everything else is a method on the Mechanic object they return.
local RunService = game:GetService("RunService")
local Mechanic = require(path.to.Mechanic)
local Spinner = Mechanic.new("Spinner", {
Shared = { Speed = 2 }, -- copied into every instance's Data table
ClassNames = { "BasePart" },
Ancestors = { workspace },
})
Spinner:OnAdded(function(part, applied, trove)
local data = applied:GetData()
trove:Connect(RunService.Heartbeat, function(dt)
part.CFrame *= CFrame.Angles(0, data.Speed * dt, 0)
end)
end)
Spinner:OnRemoved(function(part)
print(part.Name, "stopped spinning")
end)
-- Later: tag a part manually (also adds the "Spinner" tag) with custom data
Spinner:Apply(workspace.Windmill, { Speed = 0.5 })
Depends on Sleitnick's Trove and Signal, which Wally installs alongside it.
Credits: Trove and Signal are by sleitnick (sleitnick's RbxUtil). Wally installs both.
Installation and guide: Mechanic package page.
Types
Constructable
type Constructable = {new: (U...) → T}
A class table with a new constructor, as accepted by newConstructor and bindToClass. The
constructor is called through Trove:Construct as new(instance, trove) and its result becomes
the AppliedMechanic's Data.
MechanicConfig
interface MechanicConfig {Shared: T?--
Table that is shallow-copied into each instance's Data (and exposed as Shared). Defaults to {}.
Ancestors: {U}?--
Instances the tagged instance must be a descendant of (any one of them). Empty means no ancestor filter.
ClassNames: {string}?--
Class names the instance must match with IsA (any one of them). Empty means no class filter.
CustomPredicate: ((Instance) → boolean)?--
Extra check run after the other filters; return false to reject the instance.
}
Configuration passed to Mechanic.new to decide which tagged instances the mechanic applies to
and what data they start with. Every field is optional; an empty config applies to every
instance with the tag.
Properties
Tag
This item is read only and cannot be modified. Read OnlyMechanic.Tag: stringThe CollectionService tag this mechanic watches.
Shared
Mechanic.Shared: TThe shared table from the config (or {}). Each AppliedMechanic's Data starts as a shallow copy of it.
Applications
This item is read only and cannot be modified. Read OnlyEvery instance the mechanic is currently applied to, mapped to its AppliedMechanic. Prefer GetApplied and GetInstances.
Trove
Mechanic.Trove: TroveThe mechanic's own Trove. Everything added to it is cleaned by Destroy, including every AppliedMechanic.
InstanceAdded
This item is read only and cannot be modified. Read OnlyFires when the mechanic is applied to an instance. Receives the instance, its AppliedMechanic and the AppliedMechanic's Trove. OnAdded also replays existing applications.
InstanceRemoved
This item is read only and cannot be modified. Read OnlyFires with the instance after its AppliedMechanic is cleaned (untagged, destroyed, moved out of Ancestors, or revoked).
Functions
new
Creates a Mechanic for Tag. Instances that already have the tag and pass the filters are
applied immediately (each in its own coroutine); instances tagged later are applied as they
appear, and instances that lose the tag are revoked. When Ancestors is set, tagged instances
that are later parented under one of the ancestors are picked up too.
newConstructor
Mechanic.newConstructor(Tag: string,--
The CollectionService tag to watch.
Constructable: Constructable<C,D...>--
A class table whose new(instance, trove) builds the per-instance object.
) → Mechanic<C>--
The new mechanic; each AppliedMechanic's Data is the constructed object.
Creates a Mechanic and, for every instance it is applied to, constructs
Constructable.new(instance, trove) through the AppliedMechanic's Trove and stores the
result in the AppliedMechanic's Data. The constructed object is destroyed with the Trove
when the instance is removed. This is the closest equivalent to Binder.
local Door = {}
Door.__index = Door
function Door.new(model: Model, trove)
local self = setmetatable({ Model = model, Open = false }, Door)
trove:Connect(model.ClickDetector.MouseClick, function() self:Toggle() end)
return self
end
function Door.Toggle(self)
self.Open = not self.Open
end
function Door.Destroy(self) end
local DoorMechanic = Mechanic.newConstructor("Door", { ClassNames = { "Model" } }, Door)
bindToClass
Mechanic.bindToClass(Tag: string,--
The CollectionService tag to watch.
Constructable: Constructable<C,D...>--
A class table whose new(instance, trove) builds the per-instance object.
) → Mechanic<C>--
The new mechanic; each AppliedMechanic's Data is the constructed object.
Alias of newConstructor: identical behaviour under a Binder-style name.
GetApplied
Returns the AppliedMechanic for instance, or nil if the mechanic is not currently applied
to it.
GetInstances
Returns a new array of every instance the mechanic is currently applied to. The order is not defined.
CanBeApplied
Mechanic:CanBeApplied() → boolean--
Whether the instance passes every filter.
Runs the config filters against instance: it must IsA one of ClassNames (if any were
given), be a descendant of one of Ancestors (if any were given), and pass CustomPredicate
(if set). The tag itself is not checked.
Apply
Mechanic:Apply(data: T?--
Initial Data for the instance; defaults to a shallow copy of Shared.
) → AppliedMechanic<T>--
The new or existing applied mechanic.
Adds the tag to instance and applies the mechanic to it right away, skipping the
CanBeApplied filters. If the mechanic is already applied to the instance the existing
AppliedMechanic is returned and data is ignored.
Revoke
Removes the tag from instance and, if the mechanic is applied to it, destroys its
AppliedMechanic (cleaning its Trove and firing InstanceRemoved). Safe to call on instances
the mechanic is not applied to.
OnAdded
Mechanic:OnAdded(callback: (Trove) → ()--
Called with the instance, its AppliedMechanic and that AppliedMechanic's Trove.
) → Connection--
The signal connection; disconnect it to stop receiving new instances.
Connects callback to InstanceAdded and also runs it (in a new coroutine each) for every
instance the mechanic is already applied to. The callback receives the instance, its
AppliedMechanic and the AppliedMechanic's Trove; connect per-instance work to that Trove so it
is cleaned up when the instance goes away. The connection is added to the mechanic's Trove.
OnRemoved
Mechanic:OnRemoved() → Connection--
The signal connection.
Connects callback to InstanceRemoved, so it runs with the instance whenever an
AppliedMechanic is cleaned (the instance was untagged, destroyed, moved out of Ancestors, or
revoked). The connection is added to the mechanic's Trove.
Destroy
Mechanic:Destroy() → ()
Cleans the mechanic's Trove: every AppliedMechanic is destroyed (firing InstanceRemoved for
each), the CollectionService connections are disconnected and both signals are destroyed. Tags
are left on the instances.