Overview
DoorSystem is a production-ready, memory-efficient door management library for Roblox that uses Data-Oriented Design (DOD) principles and bit-level operations to achieve O(1) performance for all state operations.
β‘ High Performance
O(1) state operations using bit manipulation and buffer storage
π― Memory Efficient
DOD architecture with isolated memory allocation per door group
π§ Easy Integration
Fluent API design with chainable methods
π Built-in Security
Lock states, key requirements, and access control out of the box
Installation
Method 1: Manual Installation
- Download the DoorSystem.rbxm file
- Drag and drop the file into Roblox Studio
- Move the DoorSystem module to ServerScriptService
- Copy the example Main.luau to ServerScriptService
File Structure
βββ Main.luau (ServerScript)
βββ DoorSystem (ModuleScript)
βββ Core
β βββ DoorGroup.luau
βββ Utils
βββ BufferSerializer.luau (optional)
Quick Start
Here's a minimal example to get you started:
local DoorSystem = require(game.ServerScriptService.DoorSystem)
-- Create a door group
local MyDoors = DoorSystem.new(workspace.Map.Doors, {
PromptProps = { ActionText = "Open/Close" } -- optional
})
-- Define what happens when a door toggles
MyDoors:SetCallback(function(door, isOpen, player)
door.Transparency = isOpen and 0.8 or 0
door.CanCollide = not isOpen
end)
-- That's it! Your doors are ready to use
API Reference
DoorSystem.new()
Creates and returns a new DoorGroup instance with isolated memory allocation.
Syntax
DoorSystem.new(folder: Folder, config: table?) β DoorGroup
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
folder |
Folder | Required | The folder containing door instances |
config |
table | Optional | Configuration table (see configuration section) |
Returns
A DoorGroup object with chainable methods.
Example
-- Basic usage
local doors = DoorSystem.new(workspace.Doors)
-- With configuration
local secureDoors = DoorSystem.new(workspace.SecureDoors, {
RequiredKey = "Keycard", -- optional
PromptProps = { -- optional
ActionText = "Access Panel",
HoldDuration = 1.5
}
})
SetCallback()
Defines the behavior when a door is successfully toggled.
Syntax
DoorGroup:SetCallback(fn: function) β DoorGroup
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
fn |
function | Required | Callback function(door, isOpen, player) |
Callback Arguments
| Argument | Type | Description |
|---|---|---|
door |
Instance | The door instance that was toggled |
isOpen |
boolean | The new state (true = open, false = closed) |
player |
Player? | The player who triggered it (nil for system calls) |
Example
doors:SetCallback(function(door, isOpen, player)
-- Animate the door
door.Transparency = isOpen and 0.8 or 0
door.CanCollide = not isOpen
-- Play sound
if isOpen then
door.OpenSound:Play()
else
door.CloseSound:Play()
end
-- Log who opened it
if player then
print(player.Name .. " toggled " .. door.Name)
end
end)
SetDeniedCallback()
Defines the behavior when access is denied (locked or missing key).
Syntax
DoorGroup:SetDeniedCallback(fn: function) β DoorGroup
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
fn |
function | Required | Callback function(door, player, reason) |
Callback Arguments
| Argument | Type | Description |
|---|---|---|
door |
Instance | The door instance |
player |
Player | The player who was denied access |
reason |
string | "Locked" or "MissingKey" |
Example
doors:SetDeniedCallback(function(door, player, reason)
if reason == "Locked" then
warn(player.Name .. " tried to open locked door: " .. door.Name)
-- Play error sound
door.ErrorSound:Play()
elseif reason == "MissingKey" then
-- Send notification to player
game.ReplicatedStorage.Notify:FireClient(player, "You need a keycard!")
end
end)
OpenAll()
Opens all doors in the group instantly.
Syntax
DoorGroup:OpenAll() β DoorGroup
Example
-- Emergency evacuation: open all doors
doors:OpenAll()
-- Chain with other methods
doors:UnlockAll():OpenAll()
CloseAll()
Closes all doors in the group instantly.
Syntax
DoorGroup:CloseAll() β DoorGroup
Example
-- Lockdown protocol
doors:CloseAll():SetLockedAll(true)
SetLocked()
Sets the lock state of a specific door.
Syntax
DoorGroup:SetLocked(door: Instance, isLocked: boolean) β DoorGroup
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
door |
Instance | Required | The door instance to lock/unlock |
isLocked |
boolean | Required | true to lock, false to unlock |
Example
-- Lock a specific door
local mainDoor = workspace.Doors.MainEntrance
doors:SetLocked(mainDoor, true)
-- Unlock it later
doors:SetLocked(mainDoor, false)
SetLockedAll()
Sets the lock state of all doors in the group.
Syntax
DoorGroup:SetLockedAll(isLocked: boolean) β DoorGroup
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
isLocked |
boolean | Required | true to lock all, false to unlock all |
Example
-- Security lockdown
doors:SetLockedAll(true)
-- End lockdown
doors:SetLockedAll(false)
Unlock()
Unlocks a specific door (convenience method).
Syntax
DoorGroup:Unlock(door: Instance) β DoorGroup
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
door |
Instance | Required | The door instance to unlock |
Example
doors:Unlock(workspace.Doors.MainEntrance)
UnlockAll()
Unlocks all doors in the group (convenience method).
Syntax
DoorGroup:UnlockAll() β DoorGroup
Example
doors:UnlockAll()
Configuration
The configuration table passed to DoorSystem.new() accepts the following options:
| Option | Type | Required | Description |
|---|---|---|---|
RequiredKey |
string | Optional | Name of tool/item required in player's character to open doors |
PromptProps |
table | Optional | Properties to apply to ProximityPrompts |
PromptProps Options
Any valid ProximityPrompt property can be set. Common options:
| Property | Type | Description |
|---|---|---|
ActionText |
string | Text shown on the prompt |
HoldDuration |
number | Seconds player must hold to trigger |
KeyboardKeyCode |
Enum | Keyboard key to trigger prompt |
ObjectText |
string | Name of the object being interacted with |
Example Configuration
local config = {
RequiredKey = "SecurityCard", -- optional
PromptProps = { -- optional
ActionText = "Access Panel",
ObjectText = "Security Door",
HoldDuration = 2,
KeyboardKeyCode = Enum.KeyCode.E
}
}
local doors = DoorSystem.new(workspace.SecureDoors, config)
Examples
Basic Door System
local DoorSystem = require(game.ServerScriptService.DoorSystem)
-- Simple doors that just change transparency
local basicDoors = DoorSystem.new(workspace.BasicDoors)
:SetCallback(function(door, isOpen)
door.Transparency = isOpen and 0.8 or 0
door.CanCollide = not isOpen
end)
Secure Area with Keycard
-- Doors that require a keycard
local secureDoors = DoorSystem.new(workspace.SecureArea, {
RequiredKey = "Keycard",
PromptProps = {
ActionText = "Scan Keycard",
HoldDuration = 1
}
})
:SetCallback(function(door, isOpen, player)
door.Transparency = isOpen and 0.5 or 0
door.CanCollide = not isOpen
door.AccessLight.Color = isOpen and Color3.new(0, 1, 0) or Color3.new(1, 0, 0)
end)
:SetDeniedCallback(function(door, player, reason)
if reason == "MissingKey" then
print(player.Name .. " needs a keycard!")
door.ErrorSound:Play()
end
end)
Emergency Lockdown System
local allDoors = DoorSystem.new(workspace.AllDoors)
:SetCallback(function(door, isOpen)
door.Transparency = isOpen and 0.7 or 0
door.CanCollide = not isOpen
end)
-- Trigger lockdown on event
game.ReplicatedStorage.EmergencyLockdown.Event:Connect(function()
print("π¨ LOCKDOWN INITIATED")
allDoors
:CloseAll() -- Close all doors
:SetLockedAll(true) -- Lock them
-- Unlock after 60 seconds
task.delay(60, function()
print("β
Lockdown lifted")
allDoors:SetLockedAll(false)
end)
end)
Multiple Door Groups
-- Public areas - no restrictions
local publicDoors = DoorSystem.new(workspace.Public, {
PromptProps = { ActionText = "Open/Close" }
})
:SetCallback(function(door, isOpen)
door.Transparency = isOpen and 0.8 or 0
door.CanCollide = not isOpen
end)
-- Staff areas - require staff pass
local staffDoors = DoorSystem.new(workspace.StaffOnly, {
RequiredKey = "StaffPass",
PromptProps = {
ActionText = "Staff Access",
HoldDuration = 0.5
}
})
:SetCallback(function(door, isOpen, player)
door.Transparency = isOpen and 0.5 or 0
door.CanCollide = not isOpen
if player then
print("Staff access: " .. player.Name)
end
end)
:SetDeniedCallback(function(door, player)
warn("Unauthorized access attempt by " .. player.Name)
end)
-- Admin vault - require admin key + longer hold
local vaultDoors = DoorSystem.new(workspace.Vault, {
RequiredKey = "AdminKey",
PromptProps = {
ActionText = "Admin Access",
HoldDuration = 3
}
})
:SetCallback(function(door, isOpen, player)
door.Transparency = isOpen and 0.3 or 0
door.CanCollide = not isOpen
door.AlarmLight.Enabled = isOpen
if isOpen and player then
warn("β οΈ VAULT OPENED BY: " .. player.Name)
end
end)
Timed Auto-Close Doors
local autoDoors = DoorSystem.new(workspace.AutoDoors)
:SetCallback(function(door, isOpen)
door.Transparency = isOpen and 0.8 or 0
door.CanCollide = not isOpen
-- Auto-close after 5 seconds
if isOpen then
task.delay(5, function()
-- Re-close the door by finding it in the group
local doorGroup = autoDoors
local id = doorGroup.InstanceToId[door]
if id then
doorGroup:_setState(id, false)
door:SetAttribute("IsOpen", false)
-- Trigger callback
door.Transparency = 0
door.CanCollide = true
end
end)
end
end)
Sound Effects and Animations
local animatedDoors = DoorSystem.new(workspace.AnimatedDoors)
:SetCallback(function(door, isOpen, player)
local tween = game:GetService("TweenService")
local info = TweenInfo.new(0.5, Enum.EasingStyle.Quad)
if isOpen then
-- Slide door to the side
tween:Create(door, info, {CFrame = door.CFrame * CFrame.new(0, 0, -5)}):Play()
door.OpenSound:Play()
else
-- Slide back to original position
tween:Create(door, info, {CFrame = door.CFrame * CFrame.new(0, 0, 5)}):Play()
door.CloseSound:Play()
end
door.CanCollide = not isOpen
end)
Best Practices
1. Organize Doors in Folders
Group related doors in workspace folders for better organization and independent control:
Workspace
βββ PublicDoors
βββ SecureDoors
βββ AdminDoors
2. Use Method Chaining
All methods return the DoorGroup, allowing for clean, fluent code:
doors
:SetCallback(openCallback)
:SetDeniedCallback(deniedCallback)
:UnlockAll()
3. Separate Logic from Aesthetics
Define your callbacks separately for better maintainability:
local Callbacks = {
Standard = function(door, isOpen)
-- Animation logic here
end,
Secure = function(door, isOpen, player)
-- Secure door logic here
end
}
doors:SetCallback(Callbacks.Standard)
4. Handle Edge Cases
Always check if player exists when it might be nil:
:SetCallback(function(door, isOpen, player)
if player then
print(player.Name .. " opened the door")
else
print("System opened the door")
end
end)
5. Use task.spawn for Callbacks
Callbacks are automatically spawned in new threads to prevent yielding. You can safely use wait() or other yielding functions inside callbacks.
Technical Details
Performance Characteristics
- State Operations: O(1) using bit manipulation
- Lock Operations: O(1) using separate lock buffer
- Memory per Door: 1 bit for state + 1 bit for lock = 2 bits
- Buffer Size: ceil(doorCount / 8) bytes per buffer
Architecture
DoorSystem uses Data-Oriented Design (DOD) principles:
- Isolated memory allocation per door group
- Bit-packed state storage for cache efficiency
- Weak-keyed instance registry for O(1) lookups
- Native Luau optimization hints (@native)
Attributes
Each door automatically gets an IsOpen attribute that reflects its current state. You can read this attribute from client scripts:
-- Client script
local door = workspace.Doors.MainDoor
print(door:GetAttribute("IsOpen")) -- true or false