flatbedj/roblox-skills

luau-best-practices

Use when writing, reviewing, or refactoring Luau code for Roblox - modules, services, controllers, error handling (pcall), memory leaks and connection cleanup, server-authoritative security, input validation, naming conventions, or project organization.

ソースを見る

使い方

  1. インストールコマンドをコピーし、自分の環境へ導入する前にソースを確認します。
  2. 必要なツール、認証情報、対応環境を原文で確認します。
  3. 入力と成果物を指定し、出力を資料と照合します。
npx skills add https://github.com/flatbedj/roblox-skills --skill luau-best-practices

開始前の確認

  • 導入にはモデル契約、API枠、ファイルへのアクセス許可は含まれません。
  • スター数や導入数は活動の指標であり、独立した品質・安全性試験ではありません。
リポジトリの原文

見出し、例、コード、表、リンク、参照画像を含む原文を表示しています。

Luau Best Practices

Production-quality patterns for Roblox game development.

Core Principles

  1. Server Authority - Server owns game state; client is for presentation
  2. Fail Fast - Validate early, error loudly in development
  3. Explicit > Implicit - Clear intent beats clever code
  4. Minimal Surface Area - Expose only what's needed

Code Style

Naming Conventions

lua
-- PascalCase: Types, Classes, Services, Modules
type PlayerData = { ... }
local ShopService = {}
local PlayerController = require(...)

-- camelCase: Variables, functions, methods
local playerCount = 0
local function getPlayerData() end
function ShopService:purchaseItem() end

-- SCREAMING_SNAKE_CASE: Constants
local MAX_PLAYERS = 50
local DEFAULT_HEALTH = 100

-- Private with underscore prefix
local function _validateInput() end
local _cache = {}

File Organization

Order within a file: --!strict → services/imports → constants → types → module table → private state → private functions → public API → return. Full template in references/code-style.md.

Module Patterns

Service Pattern (Server)

lua
--!strict
local MyService = {}

local _started = false

function MyService:Start()
    assert(not _started, "MyService already started")
    _started = true
    -- Initialize connections, load data
end

function MyService:Stop()
    -- Cleanup for hot-reloading
end

return MyService

Controller Pattern (Client)

lua
--!strict
local MyController = {}

local _player = game:GetService("Players").LocalPlayer

function MyController:Init()
    -- Setup without yielding
end

function MyController:Start()
    -- Connect events, start loops
end

return MyController

More patterns (signals, state management, lazy init) in references/patterns.md.

Error Handling

Use pcall for External Calls

lua
-- DataStore, HTTP, any Roblox API that can fail
local success, result = pcall(function()
    return dataStore:GetAsync(key)
end)

if not success then
    warn("DataStore failed:", result)
    return nil
end

return result

Use assert for programming errors (things that should never happen); use pcall + warn for external calls that legitimately fail. Result types and retry patterns in references/error-handling.md.

Memory Management

Always Disconnect

lua
local connection: RBXScriptConnection

connection = event:Connect(function()
    -- handler
end)

-- Later, cleanup:
connection:Disconnect()

Use Maids/Janitors

lua
local Maid = require(Packages.Maid)

local maid = Maid.new()

maid:GiveTask(event:Connect(handler))
maid:GiveTask(instance)
maid:GiveTask(function()
    -- Custom cleanup
end)

-- Cleanup everything at once
maid:Destroy()

Weak tables for caches and other leak prevention patterns in references/memory.md.

Security Best Practices

Server Authority

lua
-- BAD: Client tells server what happened
RemoteEvent.OnServerEvent:Connect(function(player, damage)
    target.Health -= damage  -- Client controls damage!
end)

-- GOOD: Server calculates everything
RemoteEvent.OnServerEvent:Connect(function(player, targetId)
    local target = getValidTarget(player, targetId)
    if not target then return end

    local damage = calculateDamage(player)  -- Server calculates
    target.Health -= damage
end)

Validate All Input

lua
RemoteFunction.OnServerInvoke = function(player, itemId, quantity)
    -- Type validation
    if typeof(itemId) ~= "string" then return end
    if typeof(quantity) ~= "number" then return end

    -- Range validation
    if quantity < 1 or quantity > 99 then return end
    if quantity ~= math.floor(quantity) then return end

    -- Business logic validation
    if not Items[itemId] then return end
    if not canAfford(player, itemId, quantity) then return end

    -- Now safe to process
    return purchaseItem(player, itemId, quantity)
end

Rate limiting and anti-exploit patterns in references/security.md.

Common Anti-Patterns

Avoid

lua
-- Using wait() - use task.wait()
wait(1)  -- BAD
task.wait(1)  -- GOOD

-- spawn() - use task.spawn()
spawn(fn)  -- BAD
task.spawn(fn)  -- GOOD

-- delay() - use task.delay()
delay(1, fn)  -- BAD
task.delay(1, fn)  -- GOOD

-- Polling when events exist
while true do
    if something then break end
    task.wait()
end
-- GOOD: Use events/signals instead

-- String concatenation in loops
local s = ""
for i = 1, 1000 do
    s = s .. tostring(i)  -- O(n²)
end
-- GOOD: Use table.concat

-- Dot-index chains on instances
workspace.Folder.SubFolder.Part  -- Errors if missing
-- GOOD: Safe navigation
local folder = workspace:FindFirstChild("Folder")
local subFolder = folder and folder:FindFirstChild("SubFolder")
local part = subFolder and subFolder:FindFirstChild("Part")

Prefer

lua
-- Generalized iteration
for _, v in ipairs(array) do end  -- OLD
for _, v in array do end  -- MODERN (Luau)

-- If expressions
local x = if condition then a else b  -- Clean ternary

-- Continue in loops
for _, item in items do
    if not item.valid then continue end
    process(item)
end

-- Optional chaining with and
local name = player and player.Character and player.Character.Name

Project Structure

src/
├── Server/
│   ├── init.server.luau      # Bootstrap
│   ├── Services/             # Game services
│   │   ├── DataService.luau
│   │   └── CombatService.luau
│   └── Components/           # Server components
├── Client/
│   ├── init.client.luau      # Bootstrap
│   ├── Controllers/          # Client controllers
│   └── UI/                   # UI components
├── Shared/
│   ├── Types.luau            # Shared type definitions
│   ├── Constants.luau        # Shared constants
│   └── Util/                 # Shared utilities
└── Packages/                 # Wally packages

Quick Reference

DoDon't
task.wait()wait()
task.spawn()spawn()
task.delay()delay()
for _, v in tfor _, v in pairs(t)
Validate on serverTrust client data
Use typesUse any everywhere
Disconnect eventsLeave connections dangling
Use constantsMagic numbers/strings
Early returnDeep nesting
Small functions200+ line functions

References

タスクに関連する項目

同じリポジトリから

関連する Skills

すべての Skills
flatbedj
コミュニティ

roblox-networking

Use for Roblox multiplayer communication across the client-server boundary: designing RemoteEvent, UnreliableRemoteEvent, and RemoteFunction flows; validating client requests; handling replication-aware gameplay; applying rate limits and anti-exploit checks; reasoning about network ownership, server-authority patterns, Input Action System use in authoritative gameplay, and streaming-sensitive multiplayer correctness.

導入数
1
GitHub Stars
0
更新日
9月20日
flatbedj
コミュニティ

roblox-cloud

Use for Roblox Open Cloud and external integration work: choosing API-key-based authentication for server-to-server automation, constructing and troubleshooting Open Cloud REST requests, checking scopes and rate limits, determining whether HttpService can call an endpoint, setting up webhook receivers, and using Roblox OpenAPI and reference JSON artifacts for tooling or client generation.

導入数
1
GitHub Stars
0
更新日
9月20日
flatbedj
コミュニティ

roblox-game-marketing-art

Create and refine Roblox game discovery icons and thumbnails using this user's visual preferences, reference research, and approved-art continuity. Use for promotional artwork, not in-game GUI design.

導入数
1
GitHub Stars
0
更新日
9月20日
flatbedj
コミュニティ

roblox-studio-emulation

Use when you need to test a Roblox game under conditions a solo Studio playtest can't reach — mobile/tablet/phone (device emulation, TouchEnabled), multiplayer features (parties, co-op, trading, anything needing a 2nd player), or any client state that normally requires another person. Covers driving Studio's Test menu via AppleScript and simulating multiplayer by firing real remotes from the Server VM. Load this INSTEAD of telling the user "I can't test that myself".

導入数
1
GitHub Stars
0
更新日
9月20日