重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/dig1t/skills --skill luau-best-practices适用于 Roblox 游戏开发的生产级模式。
-- PascalCase: 类型、类、服务、模块
type PlayerData = { ... }
local ShopService = {}
local PlayerController = require(...)
-- camelCase: 变量、函数、方法
local playerCount = 0
local function getPlayerData() end
function ShopService:purchaseItem() end
-- SCREAMING_SNAKE_CASE: 常量
local MAX_PLAYERS = 50
local DEFAULT_HEALTH = 100
-- 私有成员使用下划线前缀
local function _validateInput() end
local _cache = {}
--!strict
-- 1. 服务/导入放在顶部
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Signal = require(ReplicatedStorage.Packages.Signal)
local Types = require(script.Parent.Types)
-- 2. 常量
local MAX_RETRIES = 3
local TIMEOUT = 5
-- 3. 类型
type Config = {
enabled: boolean,
maxItems: number,
}
-- 4. 模块表
local MyModule = {}
-- 5. 私有状态
local _initialized = false
local _cache: { [string]: any } = {}
-- 6. 私有函数
local function _helperFunction()
end
-- 7. 公共 API
function MyModule.init()
end
function MyModule.doSomething()
end
-- 8. 返回
return MyModule
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
--!strict
local MyService = {}
local _started = false
function MyService:Start()
assert(not _started, "MyService already started")
_started = true
-- 初始化连接,加载数据
end
function MyService:Stop()
-- 热重载时的清理工作
end
return MyService
--!strict
local MyController = {}
local _player = game:GetService("Players").LocalPlayer
function MyController:Init()
-- 无阻塞的初始化设置
end
function MyController:Start()
-- 连接事件,启动循环
end
return MyController
local _data: PlayerData? = nil
local function getData(): PlayerData
if not _data then
_data = loadExpensiveData()
end
return _data
end
-- DataStore、HTTP、任何可能失败的 Roblox API
local success, result = pcall(function()
return dataStore:GetAsync(key)
end)
if not success then
warn("DataStore failed:", result)
return nil
end
return result
type Result<T> =
{ ok: true, value: T } |
{ ok: false, error: string }
local function fetchData(id: string): Result<Data>
local success, data = pcall(function()
return dataStore:GetAsync(id)
end)
if not success then
return { ok = false, error = tostring(data) }
end
return { ok = true, value = data }
end
-- 使用 assert 处理那些绝不应该发生的情况
function processPlayer(player: Player)
assert(player, "player is required")
assert(player:IsA("Player"), "expected Player instance")
-- ...
end
有关完整模式,请参阅 references/error-handling.md。
local connection: RBXScriptConnection
connection = event:Connect(function()
-- 处理程序
end)
-- 稍后,进行清理:
connection:Disconnect()
local Maid = require(Packages.Maid)
local maid = Maid.new()
maid:GiveTask(event:Connect(handler))
maid:GiveTask(instance)
maid:GiveTask(function()
-- 自定义清理
end)
-- 一次性清理所有内容
maid:Destroy()
local cache = setmetatable({}, { __mode = "v" })
-- 当没有其他引用存在时,值会被垃圾回收
cache[key] = expensiveObject
有关防止泄漏的模式,请参阅 references/memory.md。
-- 错误做法:客户端告诉服务器发生了什么
RemoteEvent.OnServerEvent:Connect(function(player, damage)
target.Health -= damage -- 客户端控制伤害!
end)
-- 正确做法:服务器计算一切
RemoteEvent.OnServerEvent:Connect(function(player, targetId)
local target = getValidTarget(player, targetId)
if not target then return end
local damage = calculateDamage(player) -- 服务器计算
target.Health -= damage
end)
RemoteFunction.OnServerInvoke = function(player, itemId, quantity)
-- 类型验证
if typeof(itemId) ~= "string" then return end
if typeof(quantity) ~= "number" then return end
-- 范围验证
if quantity < 1 or quantity > 99 then return end
if quantity ~= math.floor(quantity) then return end
-- 业务逻辑验证
if not Items[itemId] then return end
if not canAfford(player, itemId, quantity) then return end
-- 现在可以安全处理了
return purchaseItem(player, itemId, quantity)
end
local lastAction: { [Player]: number } = {}
local COOLDOWN = 0.5
local function isRateLimited(player: Player): boolean
local now = os.clock()
local last = lastAction[player] or 0
if now - last < COOLDOWN then
return true
end
lastAction[player] = now
return false
end
有关全面的安全模式,请参阅 references/security.md。
-- 使用 wait() - 改用 task.wait()
wait(1) -- 错误
task.wait(1) -- 正确
-- spawn() - 改用 task.spawn()
spawn(fn) -- 错误
task.spawn(fn) -- 正确
-- delay() - 改用 task.delay()
delay(1, fn) -- 错误
task.delay(1, fn) -- 正确
-- 在有事件可用时进行轮询
while true do
if something then break end
task.wait()
end
-- 正确:改用事件/信号
-- 在循环中进行字符串拼接
local s = ""
for i = 1, 1000 do
s = s .. tostring(i) -- O(n²)
end
-- 正确:使用 table.concat
-- FindFirstChild 链式调用
workspace.Folder.SubFolder.Part -- 如果缺失会报错
-- 正确:安全导航
local folder = workspace:FindFirstChild("Folder")
local part = folder and folder:FindFirstChild("SubFolder")
and folder.SubFolder:FindFirstChild("Part")
-- 通用迭代
for _, v in ipairs(array) do end -- 旧式
for _, v in array do end -- 现代 (Luau)
-- If 表达式
local x = if condition then a else b -- 简洁的三元运算
-- 循环中的 continue
for _, item in items do
if not item.valid then continue end
process(item)
end
-- 使用 and 进行可选链式调用
local name = player and player.Character and player.Character.Name
src/
├── Server/
│ ├── init.server.luau # 引导程序
│ ├── Services/ # 游戏服务
│ │ ├── DataService.luau
│ │ └── CombatService.luau
│ └── Components/ # 服务器组件
├── Client/
│ ├── init.client.luau # 引导程序
│ ├── Controllers/ # 客户端控制器
│ └── UI/ # UI 组件
├── Shared/
│ ├── Types.luau # 共享类型定义
│ ├── Constants.luau # 共享常量
│ └── Util/ # 共享工具函数
└── Packages/ # Wally 包
| 推荐做法 | 不推荐做法 |
|---|---|
task.wait() | wait() |
task.spawn() | spawn() |
task.delay() | delay() |
for _, v in t | for _, v in pairs(t) |
| 在服务器端验证 | 信任客户端数据 |
| 使用类型 | 到处使用 any |
| 断开事件连接 | 让连接悬空 |
| 使用常量 | 魔法数字/字符串 |
| 尽早返回 | 深层嵌套 |
| 小函数 | 200+ 行的函数 |
每周安装次数
56
仓库
GitHub 星标数
1
首次出现
2026年1月30日
安全审计
安装于
opencode51
gemini-cli51
codex51
github-copilot47
kimi-cli45
cursor45
Production-quality patterns for Roblox game development.
-- 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 = {}
--!strict
-- 1. Services/imports at top
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Signal = require(ReplicatedStorage.Packages.Signal)
local Types = require(script.Parent.Types)
-- 2. Constants
local MAX_RETRIES = 3
local TIMEOUT = 5
-- 3. Types
type Config = {
enabled: boolean,
maxItems: number,
}
-- 4. Module table
local MyModule = {}
-- 5. Private state
local _initialized = false
local _cache: { [string]: any } = {}
-- 6. Private functions
local function _helperFunction()
end
-- 7. Public API
function MyModule.init()
end
function MyModule.doSomething()
end
-- 8. Return
return MyModule
--!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
--!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
local _data: PlayerData? = nil
local function getData(): PlayerData
if not _data then
_data = loadExpensiveData()
end
return _data
end
-- 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
type Result<T> =
{ ok: true, value: T } |
{ ok: false, error: string }
local function fetchData(id: string): Result<Data>
local success, data = pcall(function()
return dataStore:GetAsync(id)
end)
if not success then
return { ok = false, error = tostring(data) }
end
return { ok = true, value = data }
end
-- Use assert for things that should never happen
function processPlayer(player: Player)
assert(player, "player is required")
assert(player:IsA("Player"), "expected Player instance")
-- ...
end
See references/error-handling.md for comprehensive patterns.
local connection: RBXScriptConnection
connection = event:Connect(function()
-- handler
end)
-- Later, cleanup:
connection:Disconnect()
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()
local cache = setmetatable({}, { __mode = "v" })
-- Values are garbage collected when no other references exist
cache[key] = expensiveObject
See references/memory.md for leak prevention patterns.
-- 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)
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
local lastAction: { [Player]: number } = {}
local COOLDOWN = 0.5
local function isRateLimited(player: Player): boolean
local now = os.clock()
local last = lastAction[player] or 0
if now - last < COOLDOWN then
return true
end
lastAction[player] = now
return false
end
See references/security.md for comprehensive security patterns.
-- 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
-- FindFirstChild chains
workspace.Folder.SubFolder.Part -- Errors if missing
-- GOOD: Safe navigation
local folder = workspace:FindFirstChild("Folder")
local part = folder and folder:FindFirstChild("SubFolder")
and folder.SubFolder:FindFirstChild("Part")
-- 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
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
| Do | Don't |
|---|---|
task.wait() | wait() |
task.spawn() | spawn() |
task.delay() | delay() |
for _, v in t | for _, v in pairs(t) |
Weekly Installs
56
Repository
GitHub Stars
1
First Seen
Jan 30, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode51
gemini-cli51
codex51
github-copilot47
kimi-cli45
cursor45
Perl安全编程指南:输入验证、注入防护与安全编码实践
1,400 周安装
流程优化工具 - 分析工作流程,识别浪费,自动化改进建议 | Anthropics
707 周安装
创业操作系统 (EOS) 完整指南:六大核心组件、V/TO工具与执行力提升方法
778 周安装
Dagster专家指南:dg CLI使用、资产管理与自动化配置
703 周安装
iOS设计指南:iPhone应用界面开发规范与最佳实践(SwiftUI/UIKit)
701 周安装
Medusa数据库迁移工具db-migrate:一键执行迁移命令,实时反馈结果
708 周安装
Parallel Agent Status - 检查研究状态与运行ID的CLI工具,支持JSON输出
705 周安装
| Validate on server | Trust client data |
| Use types | Use any everywhere |
| Disconnect events | Leave connections dangling |
| Use constants | Magic numbers/strings |
| Early return | Deep nesting |
| Small functions | 200+ line functions |