关于 roblox-luau
面向 Roblox 开发者的 Luau 脚本参考技能,涵盖引擎 API、脚本运行位置及客户端与服务器通信,并提供 Studio 项目的实践模式和检查方法。
主要功能
- 01Roblox 服务与 Instance
- 02Script、LocalScript 和 ModuleScript 的职责
- 03事件处理与连接清理
- 04客户端与服务器 Remotes 及验证
- 05Studio 测试与静态分析
适用场景
- 01创建并配置 Roblox 对象
- 02选择服务器或客户端脚本位置
- 03实现事件驱动的游戏逻辑
- 04在服务器验证客户端请求
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill roblox-luau安装后在 Claude Code 中输入/roblox-luau确认已加载。
附带文件references/client-server.md
详细介绍
Roblox Luau 脚本编写
使用 Luau 为 Roblox 体验编写脚本:服务、Instance、事件、服务器与客户端的划分,以及安全的跨边界通信。适用于当前版本的 Roblox 引擎和 Studio。
适用场景
- 编写 Roblox 脚本时使用:获取服务、创建或设置实例的父级、连接事件、决定代码在服务器还是客户端运行,或配置
RemoteEvent/RemoteFunction通信。 - 项目中包含
Script/LocalScript/ModuleScript对象、.rbxl(x)场景或 Rojo*.project.json,且代码调用game:GetService(...)时使用。
**不适用场景:**跨会话持久化数据 → roblox-datastores。远程协议架构、漏洞利用防护、速率限制、高频复制以及多客户端滥用测试 → roblox-networking。与 Roblox API 无关的通用 Lua 问题。与引擎无关的输入/保存架构 → input-systems/save-systems。
核心工作流
- **使用
game:GetService("Name")获取服务。**常见服务包括:Players、Workspace、ReplicatedStorage(客户端和服务器共享)、ServerScriptService(仅服务器端代码)、ServerStorage、RunService、UserInputService(客户端)。 - 了解代码的运行位置。
Script在服务器上运行;LocalScript在客户端上运行(位于StarterPlayerScripts、StarterGui或玩家角色中)。ModuleScript是通过require调用的共享代码。 - 有意地创建实例。
local p = Instance.new("Part"),设置其属性,然后将p.Parent最后设置(设置父级会触发复制)。 - **通过事件响应。**使用
:Connect连接Players.PlayerAdded、part.Touched或RunService.Heartbeat等信号。完成后断开连接以避免泄漏。 - 通过 Remotes 跨越客户端/服务器边界——绝不要信任客户端。
客户端通过
RemoteEvent:FireServer(...)发出请求;服务器负责验证并执行。服务器对所有游戏状态拥有权威。 - 在 Studio 中测试:使用 Play/Play Here/server+client Start;通过 Output 窗口和服务器/客户端视图切换,确认代码的运行位置。
- **如果项目已有静态检查工具,请在打开 Studio 前运行检查。**在根目录的
selene.toml中添加std = "roblox",然后运行selene .。 对于 Rojo 项目,先运行一次rojo sourcemap default.project.json --output sourcemap.json生成 sourcemap,再运行luau-lsp analyze --sourcemap=sourcemap.json src,并通过--definitions传入 Roblox 类型定义(luau-lsp analyze --help会列出标志)。使用 Studio Script Sync 的项目可能没有 sourcemap。
模式
1. 服务器脚本:响应玩家加入(leaderstats)
-- ServerScriptService/Leaderboard.server.luau (a Script = runs on the server)
local Players = game:GetService("Players")
local function onPlayerAdded(player: Player)
local stats = Instance.new("Folder")
stats.Name = "leaderstats" -- this name makes it show on the leaderboard
local coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Value = 0
coins.Parent = stats
stats.Parent = player -- parent LAST
end
Players.PlayerAdded:Connect(onPlayerAdded)
2. 创建并配置实例
local Workspace = game:GetService("Workspace")
local part = Instance.new("Part")
part.Size = Vector3.new(4, 1, 4)
part.Position = Vector3.new(0, 10, 0)
part.Anchored = true -- won't fall under gravity
part.BrickColor = BrickColor.new("Bright blue")
part.Parent = Workspace -- set Parent last so it replicates once, fully
3. 连接事件(并断开连接以避免泄漏)
local debounce = false
local connection
connection = part.Touched:Connect(function(hit: BasePart)
local character = hit.Parent
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
if not humanoid or debounce then return end
debounce = true
humanoid.Health -= 10
task.wait(1) -- task.wait, NOT the deprecated wait()
debounce = false
end)
-- Later, when the part is removed or the round ends:
-- connection:Disconnect()
4. 客户端 → 服务器:使用 RemoteEvent(在服务器上验证!)
-- ReplicatedStorage: create a RemoteEvent named "BuyItem" (in Studio or via code).
-- CLIENT (LocalScript): request a purchase. The client can lie — this is only a request.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local buyItem = ReplicatedStorage:WaitForChild("BuyItem") -- wait: may not have replicated yet
buyButton.MouseButton1Click:Connect(function()
buyItem:FireServer("sword") -- send the item id only; never the price/result
end)
-- SERVER (Script): the ONLY place the transaction is decided.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local buyItem = ReplicatedStorage:WaitForChild("BuyItem")
local PRICES = { sword = 100, shield = 75 }
buyItem.OnServerEvent:Connect(function(player: Player, itemId)
-- TRUST NOTHING from the client. Validate types and values.
if type(itemId) ~= "string" then return end
local price = PRICES[itemId]
if not price then return end -- unknown item
local coins = player.leaderstats.Coins
if coins.Value < price then return end -- can't afford
coins.Value -= price -- server applies the change
grantItem(player, itemId)
end)
5. 使用 RunService 编写逐帧循环
local RunService = game:GetService("RunService")
-- Heartbeat fires every frame AFTER physics; dt is seconds since the last step.
RunService.Heartbeat:Connect(function(dt)
spinner.CFrame *= CFrame.Angles(0, math.rad(90) * dt, 0) -- 90deg/sec, frame-independent
end)
6. 在 ModuleScript 中编写共享代码
-- ReplicatedStorage/GameConfig (a ModuleScript) — usable by server and client.
local GameConfig = {}
GameConfig.MaxHealth = 100
function GameConfig.damageFor(weapon: string): number
return ({ sword = 25, bow = 15 })[weapon] or 0
end
return GameConfig
local GameConfig = require(game:GetService("ReplicatedStorage"):WaitForChild("GameConfig"))
print(GameConfig.MaxHealth)
常见陷阱
- 信任客户端就是一种漏洞利用方式 → 客户端可以向
RemoteEvent/RemoteFunction发送任意参数。在服务端验证每个参数的类型和取值范围,并确保服务端始终对生命值、货币和物品栏拥有决定权。 LocalScript不会在你放置它的位置运行 → LocalScript 只能在StarterPlayerScripts、StarterCharacterScripts、StarterGui或工具中运行,不能在Workspace或ServerScriptService中运行。服务端的Script应放在ServerScriptService/Workspace中。- 已弃用的全局函数 → 使用
task.wait/task.spawn/task.delay,而不是旧的wait()/spawn()/delay()(调度效果更差,且会受到节流)。 - 先设置父级,再设置属性 → 先设置属性,最后设置
Parent,这样实例只会以最终状态复制一次。 - 加入后客户端立即得到
nil→ 对象会随着时间逐步流式加载/复制;在客户端使用parent:WaitForChild("Name"),而不是直接索引。 - 连接从未断开 → 长期存在的
:Connect处理程序会造成泄漏,并且可能在对象销毁后触发;保存连接并调用:Disconnect()(或在适当情况下使用Instance:GetAttributeChangedSignal/:Once)。 - 适合使用
RemoteEvent时却用了RemoteFunction→RemoteFunction会阻塞,等待返回值;恶意或响应缓慢的客户端可能拖住服务端。除非确实需要回复,否则优先使用单向的RemoteEvent。 - 想当然地认为使用的是旧版类型检查器 -> Luau 的 New Type Solver 已于 2025 年 11 月正式发布(退出 Studio Beta)。
nocheck/非严格模式的位置会自动使用它;严格模式的位置可通过工作区属性UseNewLuauTypeSolver启用,而LuauTypeCheckMode用于设置位置的默认检查模式。它仅在编辑时运行(不产生运行时开销),因此排查类型警告时,应以该位置实际启用的求解器为准,而不是较旧的行为。
参考资料
- 如需了解完整的客户端/服务端模型(复制、
RemoteFunction与RemoteEvent的区别、:WaitForChild的时序、用于同一上下文内消息传递的BindableEvent、属性、CollectionService标签,以及:Once/连接清理),请阅读references/client-server.md。
相关技能
roblox-datastores— 跨会话持久化玩家数据(仅限服务端)。roblox-networking— 生产环境中的远程调用约定、服务端验证、速率限制、复制、 流式加载、预测和多客户端测试。save-systems— 与引擎无关的持久化概念。game-ai/input-systems— 可在 Luau 中实现的通用 AI 和输入模式。
评论
支持 Markdown