mcpField
R
roblox-luau

roblox-luau

github.com/gamedev-skills开发5.4k6.8k 次安装1 天前更新
代码仓库

关于 roblox-luau

面向 Roblox 开发者的 Luau 脚本参考技能,涵盖引擎 API、脚本运行位置及客户端与服务器通信,并提供 Studio 项目的实践模式和检查方法。

主要功能

  1. 01Roblox 服务与 Instance
  2. 02Script、LocalScript 和 ModuleScript 的职责
  3. 03事件处理与连接清理
  4. 04客户端与服务器 Remotes 及验证
  5. 05Studio 测试与静态分析

适用场景

  1. 01创建并配置 Roblox 对象
  2. 02选择服务器或客户端脚本位置
  3. 03实现事件驱动的游戏逻辑
  4. 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。

核心工作流

  1. **使用 game:GetService("Name") 获取服务。**常见服务包括:Players、 Workspace、ReplicatedStorage(客户端和服务器共享)、ServerScriptService (仅服务器端代码)、ServerStorage、RunService、UserInputService(客户端)。
  2. 了解代码的运行位置。Script 在服务器上运行;LocalScript 在客户端上运行(位于 StarterPlayerScripts、StarterGui 或玩家角色中)。ModuleScript 是通过 require 调用的共享代码。
  3. 有意地创建实例。local p = Instance.new("Part"),设置其属性,然后将 p.Parent 最后设置(设置父级会触发复制)。
  4. **通过事件响应。**使用 :Connect 连接 Players.PlayerAdded、 part.Touched 或 RunService.Heartbeat 等信号。完成后断开连接以避免泄漏。
  5. 通过 Remotes 跨越客户端/服务器边界——绝不要信任客户端。 客户端通过 RemoteEvent:FireServer(...) 发出请求;服务器负责验证并执行。服务器对所有游戏状态拥有权威。
  6. 在 Studio 中测试:使用 Play/Play Here/server+client Start;通过 Output 窗口和服务器/客户端视图切换,确认代码的运行位置。
  7. **如果项目已有静态检查工具,请在打开 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