关于 roblox-ui
面向使用 Roblox Instances 和平台 API 的开发者的 UI 实现技能,强调可编辑层级、响应式布局、输入与焦点处理,以及跨设备测试。
主要功能
- 01ScreenGui 层级与生命周期
- 02响应式布局与约束
- 03安全区域与设备遮挡处理
- 04触控、手柄和键盘输入
- 05兼顾动态偏好的状态过渡
- 06跨设备 UI 验证
适用场景
- 01替换脆弱的像素定位界面
- 02构建背包等响应式屏幕
- 03修复焦点与手柄导航问题
- 04检查不同视口和设备上的 UI
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill roblox-ui安装后在 Claude Code 中输入/roblox-ui确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlassets/inventory-quality-test.model.jsoninventory-quality-test.project.jsonreferences/input-navigation.mdresponsive-layout.md详细介绍
Roblox UI
构建有明确设计、可编辑的 Roblox UI,保留体验的视觉语言,并适配所有受支持的设备。面向 Roblox 持续更新的平台 API。搭配 game-ui-ux 使用,获取与引擎无关的信息架构和 UX;本技能负责 Roblox Instances 和 API。
适用场景
- 用于编写
ScreenGui界面、Roblox 布局/约束 API、UI 生命周期、输入、焦点、动画、性能或响应式/设备适配。 - 用于替换脆弱的像素布局、运行时创建的 Instance 乱象、仅支持鼠标的菜单或通用的生成式样式,构建易维护的层级结构。
不适用场景: 通用 UX 流程和无障碍原则应交由 game-ui-ux;原始游戏玩法操作映射应交由 input-systems;服务端信任应交由 roblox-networking。
工作流
- 先检查,再设计。 在 Explorer 中盘点现有的
ScreenGui、UI 模块、字体、颜色、图标系列、间距、圆角、描边、动画时长、命名和可复用组件。截取两种视口下具有代表性的屏幕截图。延续现有设计语言。 - 明确所有权和生命周期。
StarterGui是编写的模板;Roblox 会将其克隆到每位玩家的PlayerGui中。确定每个ScreenGui是否应通过ResetOnSpawn = false在重生后保留;绝不要保留已销毁克隆的过期引用。 - 编写清晰易读的层级结构。 优先使用有意义、可编辑的 Instances 和小型行为模块。正常的屏幕结构应便于在 Explorer 中理解;仅在确实需要数据驱动的重复内容时使用程序化生成,不要用它构建整个外壳。
- 构建响应式结构。 结合使用
UDim2缩放定位与有界偏移、正确的AnchorPoint、布局、内边距、内容尺寸和约束。明确选择窄屏/宽屏布局,而不是不断缩小桌面面板,直到勉强适配。 - 处理平台遮挡。 将可交互 UI 放在
CoreUISafeInsets内(这是推荐的ScreenGui.ScreenInsets默认值),并考虑触控控制区域以及电视观看距离/过扫描。 - 连接状态与输入。 根据精简的视图状态进行渲染,并在事件发生时更新。对
GuiButton使用Activated,明确设置选中状态,并确保手柄导航可达。只有在屏幕拥有非控件操作期间,才使用ContextActionService绑定这些操作。 - 适度润色。 实现悬停、按下、选中和禁用状态。为状态变化添加动画,而非装饰;遵守
GuiService.ReducedMotionEnabled,并在屏幕关闭或被替换时清理补间和连接。 - 验证实际界面。 使用 Device Emulator 和 Controller Emulator。测试桌面、窄屏竖屏、移动设备横屏、类平板设备以及主机/手柄;然后重生。记录裁切、重叠、文本、滚动、安全区域、焦点路径、触控目标和生命周期测试结果。
生产结构
StarterGui
└── InventoryGui (ScreenGui; ResetOnSpawn = false)
├── Root (Frame)
│ ├── Header
│ ├── Content
│ │ ├── CategoryList
│ │ ├── ItemGrid (ScrollingFrame)
│ │ └── DetailsPanel
│ └── Footer
└── InventoryController (LocalScript)
ReplicatedStorage
└── UI
├── Components
└── Theme
名称应描述用途,而非颜色或临时位置。将重复的项目单元格保留为模板或组件,同时确保在 Explorer 中能看到编写好的外壳。
模式
适应内容和视口变化的布局
-- Authored properties on ItemGrid (ScrollingFrame):
-- AutomaticCanvasSize = Enum.AutomaticSize.Y
-- CanvasSize = UDim2.fromOffset(0, 0)
-- Children: UIPadding + UIGridLayout
local grid = itemGrid.UIGridLayout
local projectBreakpoint = 700 -- derive from where this composition stops being usable
local function applyComposition()
local narrow = root.AbsoluteSize.X < projectBreakpoint
categoryList.UIListLayout.FillDirection = if narrow
then Enum.FillDirection.Horizontal
else Enum.FillDirection.Vertical
categoryList.Size = if narrow
then UDim2.new(1, 0, 0, 40)
else UDim2.new(0, 148, 1, 0)
itemGrid.Position = if narrow then UDim2.fromOffset(0, 52) else UDim2.fromOffset(164, 0)
itemGrid.Size = if narrow
then UDim2.new(1, 0, 1, -52)
else UDim2.new(0.58, -164, 1, 0)
detailsPanel.Visible = not narrow -- open details as a separate narrow-screen state
local width = itemGrid.AbsoluteSize.X
local columns = if width < 520 then 2 elseif width < 820 then 3 else 4
local gap = 12
local usable = width - itemGrid.UIPadding.PaddingLeft.Offset
- itemGrid.UIPadding.PaddingRight.Offset - gap * (columns - 1)
grid.CellSize = UDim2.fromOffset(math.floor(usable / columns), 112)
grid.CellPadding = UDim2.fromOffset(gap, gap)
end
root:GetPropertyChangedSignal("AbsoluteSize"):Connect(applyComposition)
applyComposition()
一维排列使用 UIListLayout,统一单元格使用 UIGridLayout,只有在确实需要按行/列对齐时才使用 UITableLayout。AutomaticSize 可适应内容尺寸;AutomaticCanvasSize 可适应滚动内容尺寸。使用 UISizeConstraint、UIAspectRatioConstraint 或 UITextSizeConstraint 限制极端尺寸,而不要依赖单一的全局 UIScale 猜测值。
一条激活路径和明确的手柄入口
local GuiService = game:GetService("GuiService")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local function openInventory()
root.Visible = true
task.spawn(function()
RunService.RenderStepped:Wait() -- selection must be rendered and selectable
if root.Visible and (UserInputService.GamepadEnabled
or (UserInputService.KeyboardEnabled and not UserInputService.TouchEnabled)) then
GuiService.SelectedObject = firstItemButton
end
end)
end
local function closeInventory()
GuiService.SelectedObject = nil
root.Visible = false
end
firstItemButton.Activated:Connect(function()
selectItem(firstItemButton:GetAttribute("ItemId"))
end)
优先使用 Activated,而不是分别处理鼠标和触摸事件。自动导航存在歧义时,设置 NextSelectionUp/Down/Left/Right,尤其是网格、侧边栏和模态框附近。模态框必须将焦点限制在自身内部,并在关闭时恢复到合理的选中项。
对于跨设备操作绑定,Input Action System(InputContext/InputAction/InputBinding)是现代的编辑时层;参见 references/input-navigation.md。
结合实际界面检查 Roblox 的默认选中装饰。如果它过于醒目,请指定项目自有的 SelectionImageObject 或选中态样式;应保持其可见、有效且克制,而不是禁用焦点反馈。
无多余动画的状态转换
local TweenService = game:GetService("TweenService")
local GuiService = game:GetService("GuiService")
local fade = TweenInfo.new(0.14, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local function setPanelVisible(visible: boolean)
panel.Visible = true -- panel is a CanvasGroup
if GuiService.ReducedMotionEnabled then
panel.GroupTransparency = if visible then 0 else 1
else
TweenService:Create(panel, fade, {
GroupTransparency = if visible then 0 else 1,
}):Play()
end
if not visible then
task.delay(fade.Time, function()
if panel.GroupTransparency == 1 then panel.Visible = false end
end)
end
end
对面板或状态边界动画一次即可。不要让每个子元素都单独弹跳。
视觉质量门槛
- 先通过大小、字重、对比度、分组和留白建立层次,再添加装饰。使用小范围的间距刻度,并按其对齐。
- 保持游戏的字体、配色、图标、圆角和描边风格。如果没有现成规范,就定义一个精简的设计令牌模块;不要为每个组件临时发挥。
- 只在材质或形状需要时使用圆角,不要给每个嵌套的
Frame都加圆角。避免卡片层层嵌套、到处使用胶囊形、随意添加渐变/辉光/阴影、霓虹描边、过度透明/模糊、过大的标题、无意义的图标和巨大的空白面板。 - 重要程度不同的按钮不应看起来完全相同。仅按需定义主要、次要、弱强调、危险、选中、按下、悬停和禁用样式。
- 动画用于传达打开/关闭、焦点、确认或空间关系。动画应简短、可中断且细微;避免持续运动和装饰性的补间动画链。
- 在触屏设备上,为默认的移动/跳跃区域留出空间。移动或重新编排与其重叠的底部操作,并在键盘/手柄输入未启用时隐藏相应提示。
常见问题
| 症状 | 可能原因 | 解决方法 |
|---|---|---|
| 重生后 UI 消失或重复 | ResetOnSpawn 策略不正确或克隆已过期 | 选择合适的策略;从 PlayerGui 重新获取;清理旧绑定 |
| 手机布局被裁切 | 将桌面端偏移/全局缩放用作布局 | 添加窄屏布局、布局对象和边界,并使用 Device Emulator 检查 |
| 内容被顶栏/缺口遮挡 | 忽略了内边距,或设置了 ScreenInsets = None | 交互式 UI 使用 CoreUISafeInsets;检查有意的延伸区域 |
| 滚动提前结束 | CanvasSize 固定 | 使用 AutomaticCanvasSize 或布局的 AbsoluteContentSize |
| 控制器卡住 | 缺少入口选中项或相邻关系图错误 | 设置初始 SelectedObject;定义并测试焦点路径/模态框焦点限制 |
| UI 看起来像自动生成的 | 用装饰取代了层次结构 | 移除特效;调整对齐、减少嵌套、修正密度和组件职责 |
| 连接/补间数量不断增加 | 屏幕重新绑定但未清理 | 按屏幕生命周期管理连接;在销毁时断开连接/取消动画 |
资源
- 阅读
references/responsive-layout.md,了解布局决策、内边距策略、密度以及必需的视口矩阵。 - 在实现手柄/触摸焦点、模态框行为、操作绑定或动画偏好时,阅读
references/input-navigation.md。 - 使用 Rojo 构建
assets/inventory-quality-test.project.json(它映射相邻的 JSON 模型),以生成可编辑的 Instance 测试夹具,用于视觉/布局审查;它是测试基准,不是可上线游戏的样式模板。
相关技能
game-ui-ux— 信息层级、屏幕流程、无障碍设计和 UX 验证。input-systems— 游戏操作映射和设备切换。roblox-networking— 由 UI 发起的服务器权威请求。roblox-studio-workflow— 以 Explorer 为先的编辑方式和 Studio 验证。
主要参考资料
- Roblox Creator Hub:
https://create.roblox.com/docs/ui/on-screen-containers - Roblox Creator Hub:
https://create.roblox.com/docs/ui/position-and-size - Roblox Creator Hub:
https://create.roblox.com/docs/ui/size-modifiers - Roblox Creator Hub:
https://create.roblox.com/docs/studio/testing-modes