一个 HUD 或 头部显示器 是一组在游戏期间始终可见或可访问的 UI 元素,例如得分显示、生命值计量和菜单按钮。包含 HUD 对大多数体验来说至关重要,因为它显示有助于玩家在游戏目标中取得成功的信息。
一个常见的 HUD 元素是左侧带有图标的生命值计量单元,可以适应为计时条、进度条或类似的。

使用 危险空间站 作为起点,以及 UI基础 - HUD计量器 作为完成的参考场景,本教程展示了:
- 设置并使用 设备模拟器 来在多个模拟屏幕上测试你的设计。
- 使用 StarterGui 作为设计和存储容器的用途。
- 如何在内置 Roblox 控件和装置槽/岛上放置/调整 UI 元素,例如现代手机上的相机槽。
- 如何用自己的计量器替换默认 Roblox 生命计量器,并将其连接到角色的生命等级。
- 如何动画健康计量表的中心部分并将颜色设置在五种颜色渐变键点(红色、橙色、黄色、柠檬绿色、绿色)之间
启用设备模拟器
Roblox 本质上是跨平台的,因为玩家可以在 PC 或游戏机上发现并加入体验,然后稍后拿起手机并继续他们离关闭的地方。移动设备(手机和平板)拥有最少的屏幕空间,因此它很重要您的用户界面元素适合于更小的屏幕,并且对玩家清晰可见。
在多个平台上测试用户界面设计的最好方法是 Studio 的 设备模拟器。该工具提供预设选择的设备,并允许您添加自己的自定义预设。
在 Studio 中打开 危险空间站 模板。
从 测试 选项卡切换到 设备 工具。
从主窗口上方的工具栏直接选择一个电话模拟,例如 iPhone X 或 Samsung Galaxy A51 。然后,将视图尺寸设置为 适合窗口 以利用 Studio 中的最大空间。
创建屏幕容器
一个 ScreenGui 容器包含 UI 对象 ( GuiObjects ),用于在玩家的屏幕上显示 (在本教程中,整个生命计)要将 ScreenGui 和其子对象显示给每个加入体验的玩家,请将它放置在 StarterGui 容器内。当玩家加入并生成他们的角色时,ScreenGui 和其内容将复制到位于 PlayerGui 容器内的那个玩家的容器中,该容器位于 Players 容器内。

要插入一个空的 ScreenGui :
在 浏览器 窗口中,找到 StarterGui 容器。
将鼠标悬停在容器上,单击⊕按钮,然后插入ScreenGui。
重命名新容器 HUDContainer 反映其目的。
利用安全区域
现代手机利用整个屏幕,但通常包括占用屏幕空间的钮钮、切割和其他元素。每个 Roblox 体验还包括快速访问主菜单、聊天、排行榜等顶部栏控件以及更多内容。

为了确保玩家可以无障碍地查看和访问所有界面,Roblox 提供了 ScreenInsets 属性,该属性控制 安全区 插入的内容,用于 ScreenGui 的内容。每个你放置在 ScreenGui 内的 UI 对象都相对于插入边界。

虽然默认值 CoreUISafeInsets 确保所有用户界面对象都清除了 Roblox 用户界面和设备切割,但 DeviceSafeInsets 可以作为更好的选择来利用有限的屏幕空间,如下所示。

在 探索器 窗口中,选择 HUDContainer 。
在 属性 窗口中,将 ScreenInsets 属性设置为 DeviceSafeInsets。
设置边缘垫料
通过 ScreenInsets 设置为 DeviceSafeInsets , 内容现在可以直接延伸到屏幕的物理顶边。然而,小量的 填充 可以帮助推动健康计数器 (和容器内的其他对象) 稍微离开屏幕边缘,获得更干净的外观,并防止它们被剪切。

将 padding 应用到 UI 容器的一个方法是通过插入 UIPadding 修改器来实现的:
将 UIPadding 修改器插入 HUDContainer 。
选择了新的 UIPadding 对象,输入容器所有边缘的值 0, 16 (PaddingBottom、PaddingLeft、PaddingRight、PaddingTop)。这适用于容器周围的 16 像素填充,无论屏幕分辨率如何。
构建健康计数器
配备 屏幕容器 后,您可以使用 Roblox UI 对象,例如 框架 和一个 图像标签 开始构建健康计数器。

创建父窗口框
与像 Figma 和 Photoshop 这样的设计应用程序类似,Roblox 中的 Frame 作为其他 UI 对象的容器。在本教程中,整个生命计将包含在单个父框中,使其易于在各种 HUD 布局中重新定位。
将新框架实例重命名为 仪表板 。
位置框架
在 Roblox 中,UI 对象的位置由包含 UDim2 和 Scale 值的 Offset 坐标集来表示,其中包含 X 和 Y 轴:


要将 UI 对象放置在屏幕容器的右上角,Scale 是最好的方法,因为 X 值的 1 (100%) 代表容器的右边,无论屏幕的物理像素大小如何。同样, Y 的 0 (0%) 缩放值代表容器的顶端。

此外,您还需要为父框设置右上角的 锚点,以定义其起始点。接受的值在 和 之间,相对于对象的大小,因此 的锚值将框的锚点放在右上角。

在 浏览器 窗口中,选择你之前插入的 计量栏 框架。
输入 1, 0 为 AnchorPoint 属性。框架现在应该位于 设备安全区 的右上角,由于边缘的 填充 而略微凹陷。
调整框架大小
像位置一样,UI对象的Size 由包含 UDim2 和 Scale 值的 Offset 坐标集表示,其中包含 X 和 Y 轴的值。
默认情况下,新框的大小是 , 即宽度为 100 像素 和高度为 12 Y 。虽然在某些情况下严格的像素值有用,但许多用户界面元素在设置为整个屏幕容器尺寸的 百分比 时,在多个屏幕上的响应更大。
选择 仪表板 框架后,访问 属性窗口 并导航到 Size 属性。
输入值 0.35, 0, 0.05, 0 来设置宽度为 35% 和高度为 5% 的百分比大小,没有添加像素偏移。
框式样式
默认情况下,Frames 填充为纯白色。最终的健康计数器应具有更暗和略透明的填充,以及黑暗轮廓,以便在浅色和黑暗背景上更好地突出。

选择了 仪表板 框架,输入 0 为 BackgroundColor3 属性。工作室将自动将其转换为RGB值的 [0, 0, 0] 。
输入 0.75 为 BackgroundTransparency 属性。在 Roblox 中,透明度从 0 为完全不透明到 1 为完全透明,因此 0.75 在其他应用程序中如 Figma 或 Photoshop 等完全透明的情况下等于 25% 不透明。
为了完善计量框的样式,您可以将角落圆化,形成一个“药丸”形状而不是锋利的长方形。
将 UICorner 实例插入 仪表板 框架。
在新的 UICorner 选择中,将 CornerRadius 设置为 0.5, 0。使用 缩放值 (50%)而不是像素值来显示计量棒特别方便,因为它可以确保无论容器多高或多宽,都能保证完全圆满的曲线。
创建内部填充
现在健康计数器的含有框架已完成,你可以添加一个 内部填充 部分来代表角色的变量健康。由于只需要是填充实体区域,因此父框内的子框 Frame 很适合。

将子 Frame 插入到 计量棒 框架中。
将新框架实例重命名为 内部填充 。
选择 内部填充 ,设置以下属性:
- AnchorPoint = 0, 0.5 (左边和垂直中心)
- Position = 0, 0, 0.5, 0
- Size = 1, 0, 1, 0
由于框架的子框相对于其父元素框有位置和尺寸,因此使用缩放将内框填充父父元素的全宽和高度,从父父元素的左边开始。
要匹配父框的“药片”形状,请在 内部填充 中插入额外的 UICorner 。
选择了新的 修改器,将其 属性设置为 匹配父 计量棒 框的“药丸”形状。
为了更好地表示全尺寸表示良好的健康状况,请选择 内部填充 并将其 属性设置为 (在稍后的任务中,您将 脚本 这种颜色以根据实际健康状况进行更改)。
添加标志
为了更清楚地指示计量器的目的,您可以在左侧添加 图像标签,在这种情况下,红色心形图常常代表生命或健康。

将 ImageLabel 插入到 仪表板 框中。该对象允许您应用已上传到 Roblox 的 2D 图像资产作为贴花。
将新标签实例重命名为 图标 。
选择 图标 后,将其 ZIndex 属性设置为 2 .虽然新插入的用户界面对象总是排在之前插入的对象前面,但这个更改确保图标始终显示在仪表框元素前面。
为了确保图标 ImageLabel 始终保持 1:1 长宽比,请插入一个 UIAspectRatioConstraint 。虽然这个 约束 有可定制的属性来控制比例率,但您可以保留其默认值不变。
选择 图标 后,通过更改以下属性来完善外观和位置:
- AnchorPoint = 0.5, 0.5 (中心锚固)
- BackgroundTransparency = 1 (100% 透明)
- Position = 0, 0, 0.5, 0 (计量器左侧和垂直中心)
限制大小
虽然 缩放高度 (5%)在现代手机屏幕和游戏显示器上看起来很不错,但计量表在平板电脑屏幕和较旧手机上看起来略高了。您可以通过模拟平板电脑,例如 iPad 第七代 从 设备模拟器 来检查此情况。


为了使计量棒的高度更加一致,您可以应用 UISizeConstraint 来限制最大像素高度。
将 UISizeConstraint 插入到 仪表板 框中。
选择了新的约束后,将其 属性设置为 来限制高度为 20 像素,同时不限制宽度限制。
现在,计量条保持更一致的高度,在更宽和更高的屏幕之间。

替换默认健康计数器
Roblox 体验包括一个默认生命值计数器,当角色受到伤害时显示。如果您保留默认计量器可见,它将复制并可能覆盖自定义计量器。

禁用默认计量器
要禁用默认健康计数器,您将使用 客户端脚本 ( LocalScript ) 内的 StarterPlayerScripts 调用 StarterGui:SetCoreGuiEnabled() 。
在 资源管理器 窗口中,扩展 StarterPlayer 容器,然后在其中找到 StarterPlayerScripts 容器。
将新的 LocalScript 插入容器并将其重命名为 隐藏默认健康计量器 来描述其用途。当本地玩家加入体验时,StarterPlayerScripts 内的脚本自动运行,使其成为永久隐藏默认计量的理想容器运行脚本的容器
当你插入新脚本时,它会自动打开在新脚本编辑器选项卡中(如果没有,请在 资源管理器 窗口中双击脚本)。
在 隐藏默认健康计数器 脚本中粘贴以下代码:
隐藏默认健康计量器local StarterGui = game:GetService("StarterGui")-- 隐藏默认健康计数器StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health, false)代码说明 >线 目的 1 获取核心服务的参考,StarterGui,代表你创建了自定义健康计数器的同一个容器,其内容复制到每个加入体验的玩家的PlayerGui中。 4 调用服务的 SetCoreGuiEnabled() 方法并指示默认健康计数器被禁用 ( false )。
如果你现在玩测试体验并受到伤害,你会注意到默认计量器已被禁用并隐藏(你将编写自定义计量器来反映下一节中的健康变化))。

监听健康状况变化
所有默认 Roblox 角色模型都包含一个 Humanoid 类,提供特殊的行为和功能给角色,例如设置其步行/跑步速度和管理其健康状况。Health 服务器上的更改复制到每个玩家的客户端,你可以检测这些更改来更新既大小又颜色的自定义健康计量器。
在 浏览器 窗口中,找到 StarterCharacterScripts 容器在 StarterPlayer 内。
将新的 LocalScript 插入容器并将其重命名为 更新自定义计量器 来描述其用途。在 StarterCharacterScripts 内的脚本每次玩家角色生成时自动运行,使其成为理想的容器来运行每次重生时完全重置健康计数器的脚本。
在 UpdateCustomMeter 脚本的编辑器窗口中,粘贴以下验证码:
更新自定义计量器local Players = game:GetService("Players")-- 对本地玩家、角色和人形的参考local player = Players.LocalPlayerlocal character = player.Characterlocal humanoid = character:WaitForChild("Humanoid")-- 参考计量杆内部框架local playerGui = player:WaitForChild("PlayerGui")local meterBarInner = playerGui.HUDContainer.MeterBar.InnerFill-- 渐变顺序颜色(红、橙、黄、柠檬绿、绿)local gradient = {Color3.fromRGB(225, 50, 0),Color3.fromRGB(255, 100, 0),Color3.fromRGB(255, 200, 0),Color3.fromRGB(150, 225, 0),Color3.fromRGB(0, 225, 50)}-- 从分数点获取渐变顺序中的颜色的函数local function getColorFromSequence(fraction: number): Color3-- 渐变中的每个颜色定义了段落的开始和/或结束local numSections = #gradient - 1-- 每个部分代表 1 的一部分local sectionSize = 1 / numSections-- 确定要求的分数属于哪个部分local sectionStartIndex = 1 + math.clamp(fraction, 0, 1) // sectionSize-- 获取段落的开始和结束颜色local sectionColorStart = gradient[sectionStartIndex]local sectionColorEnd = gradient[sectionStartIndex + 1] or sectionColorStart-- 将小数正常化为段内的 0 到 1 的数字local fractionOfSection = math.clamp(fraction, 0, 1) % sectionSize / sectionSize-- 基于正常化分数的开始和结束之间的 Lerpreturn sectionColorStart:Lerp(sectionColorEnd, fractionOfSection)endlocal function onHealthChanged()-- 计算新的生命值为最大值的百分比local healthFraction = math.max(0, humanoid.Health / humanoid.MaxHealth)-- 将条设置为新的尺寸/颜色目标meterBarInner.Size = UDim2.new(healthFraction, 0, 1, 0)meterBarInner.BackgroundColor3 = getColorFromSequence(healthFraction)end-- 听取关于人形健康状况的更改humanoid.HealthChanged:Connect(onHealthChanged)-- 初始设置(或重置)栏宽度/颜色到当前健康onHealthChanged()代码说明 >线 目的 4 ‑ 6 获取本地 Player 的引用,其 Character 模型,以及其中的 Humanoid 类。 9 ‑ 10 获取计量器的 内部填充 对象的参考,该对象必须调整大小并重新着色,以反映角色的生命状况变化。 13 ‑ 19 宣言一个由五种颜色(红色、橙色、黄色、荧光绿色和绿色)组成的阵列,在各个点上重新着色计量;例如,绿色为 100% 生命值、黄色为 50%、红色为 0% 或在键点之间的任何比例的混合。 22 ‑ 41 返回任何渐变颜色键点之间颜色混合的助助函数。 43 ‑ 50 处理任何健康变化的函数。在这里,它计算新的生命值为角色的 MaxHealth 的百分比,将 内部填充 缩放到该百分比比例,然后将其重新上色为从 getColorFromSequence() 函数返回的颜色。 53 检测服务器复制的变更的主事件连接,调用功能。 56 最初(在角色生成或重生时)调用 onHealthChanged() 函数将 内部填充 的尺寸和颜色调整为正确的百分比。通常这将是全宽和绿色。
如果你现在测试体验,你会注意到随着角色受到伤害,自定义计量器正确地更新了尺寸和颜色:
动画计量棒
要给自定义计量器添加额外的波兰语等级,您可以通过 渐变 动画来改变计量器条的大小和颜色,在 ½ 秒内逐渐改变。
访问脚本编辑器选项卡,用于之前编辑的 UpdateCustomMeter 脚本。
选择所有行(CtrlA 或 ⌘A )然后粘贴到他们上面(CtrlV 或 ⌘V )以下验证码:
更新自定义计量器local Players = game:GetService("Players")local TweenService = game:GetService("TweenService")-- 对本地玩家、角色和人形的参考local player = Players.LocalPlayerlocal character = player.Characterlocal humanoid = character:WaitForChild("Humanoid")-- 过渡属性local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out)-- 参考计量杆内部框架local playerGui = player:WaitForChild("PlayerGui")local meterBarInner = playerGui.HUDContainer.MeterBar.InnerFill-- 渐变顺序颜色(红、橙、黄、柠檬绿、绿)local gradient = {Color3.fromRGB(225, 50, 0),Color3.fromRGB(255, 100, 0),Color3.fromRGB(255, 200, 0),Color3.fromRGB(150, 225, 0),Color3.fromRGB(0, 225, 50)}-- 从分数点获取渐变顺序中的颜色的函数local function getColorFromSequence(fraction: number): Color3-- 渐变中的每个颜色定义了段落的开始和/或结束local numSections = #gradient - 1-- 每个部分代表 1 的一部分local sectionSize = 1 / numSections-- 确定要求的分数属于哪个部分local sectionStartIndex = 1 + math.clamp(fraction, 0, 1) // sectionSize-- 获取段落的开始和结束颜色local sectionColorStart = gradient[sectionStartIndex]local sectionColorEnd = gradient[sectionStartIndex + 1] or sectionColorStart-- 将小数正常化为段内的 0 到 1 的数字local fractionOfSection = math.clamp(fraction, 0, 1) % sectionSize / sectionSize-- 基于正常化分数的开始和结束之间的 Lerpreturn sectionColorStart:Lerp(sectionColorEnd, fractionOfSection)endlocal function onHealthChanged()-- 计算新的生命值为最大值的百分比local healthFraction = math.max(0, humanoid.Health / humanoid.MaxHealth)-- 将栏调整到新的尺寸/颜色目标local tweenGoal = {Size = UDim2.new(healthFraction, 0, 1, 0),BackgroundColor3 = getColorFromSequence(healthFraction)}local meterBarTween = TweenService:Create(meterBarInner, tweenInfo, tweenGoal)meterBarTween:Play()end-- 听取关于人形健康状况的更改humanoid.HealthChanged:Connect(onHealthChanged)-- 初始设置(或重置)栏宽度/颜色到当前健康onHealthChanged()键添加/更改线 目的 2 获取 TweenService 的引用以在脚本中实现渐变功能。 10 创建一个 TweenInfo 建造者,定义预期的补间动画少年时间、缓解风格 和缓解方向。 52 ‑ 57 而不是单纯设置条的大小和颜色如在以前版本,宣布一个具有目标大小/颜色的tweenGoal,使用 tweenInfo 和 tweenGoal 参数创建一个新的过渡,播放新的补间动画。
如果您现在测试体验,您会注意到每次更改健康状况之间的自定义计量涡轮:
添加伤害效果
默认健康计数系统包括角色受损时屏幕边缘的淡红色渗透,当角色受损时短暂出现在屏幕边缘。通过 禁用默认计量器,此效果将被移除,但您可以用自己的实现替换它。
访问脚本编辑器选项卡,用于之前编辑的 UpdateCustomMeter 脚本。
选择所有行并使用以下代验证码粘贴到它们上面:
更新自定义计量器local Workspace = game:GetService("Workspace")local Players = game:GetService("Players")local TweenService = game:GetService("TweenService")-- 对本地玩家、角色和人形的参考local player = Players.LocalPlayerlocal character = player.Characterlocal humanoid = character:WaitForChild("Humanoid")-- 过渡属性local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out)-- 变量存储/缓存角色健康local cachedHealth = humanoid.Health / humanoid.MaxHealth-- 在玩家镜头像机内获得(或创建新)颜色修正效果local colorCorrection = Workspace.CurrentCamera:FindFirstChildWhichIsA("ColorCorrectionEffect") or Instance.new("ColorCorrectionEffect", Workspace.CurrentCamera)colorCorrection.Name = "DamageColorEffect"-- 参考计量杆内部框架local playerGui = player:WaitForChild("PlayerGui")local meterBarInner = playerGui.HUDContainer.MeterBar.InnerFill-- 渐变顺序颜色(红、橙、黄、柠檬绿、绿)local gradient = {Color3.fromRGB(225, 50, 0),Color3.fromRGB(255, 100, 0),Color3.fromRGB(255, 200, 0),Color3.fromRGB(150, 225, 0),Color3.fromRGB(0, 225, 50)}-- 从分数点获取渐变顺序中的颜色的函数local function getColorFromSequence(fraction: number): Color3-- 渐变中的每个颜色定义了段落的开始和/或结束local numSections = #gradient - 1-- 每个部分代表 1 的一部分local sectionSize = 1 / numSections-- 确定要求的分数属于哪个部分local sectionStartIndex = 1 + math.clamp(fraction, 0, 1) // sectionSize-- 获取段落的开始和结束颜色local sectionColorStart = gradient[sectionStartIndex]local sectionColorEnd = gradient[sectionStartIndex + 1] or sectionColorStart-- 将小数正常化为段内的 0 到 1 的数字local fractionOfSection = math.clamp(fraction, 0, 1) % sectionSize / sectionSize-- 基于正常化分数的开始和结束之间的 Lerpreturn sectionColorStart:Lerp(sectionColorEnd, fractionOfSection)endlocal function onHealthChanged()-- 计算新的生命值为最大值的百分比local healthFraction = math.max(0, humanoid.Health / humanoid.MaxHealth)-- 将栏调整到新的尺寸/颜色目标local tweenGoal = {Size = UDim2.new(healthFraction, 0, 1, 0),BackgroundColor3 = getColorFromSequence(healthFraction)}local meterBarTween = TweenService:Create(meterBarInner, tweenInfo, tweenGoal)meterBarTween:Play()-- 如果新生命值低于缓存生命值,显示伤害效果if healthFraction < cachedHealth then-- 缓存新的生命值cachedHealth = healthFraction-- 将颜色修正设置为红色,作为渐变之前的初始色调colorCorrection.TintColor = Color3.fromRGB(255, 25, 25)colorCorrection.Saturation = 2.5-- 将色调调回白色(中立且没有色调变化从普通)local colorCorrectionTweenGoal = {TintColor = Color3.fromRGB(255, 255, 255),Saturation = 0}local colorCorrectionTween = TweenService:Create(colorCorrection, tweenInfo, colorCorrectionTweenGoal)colorCorrectionTween:Play()endend-- 听取关于人形健康状况的更改humanoid.HealthChanged:Connect(onHealthChanged)-- 初始设置(或重置)栏宽度/颜色到当前健康onHealthChanged()键添加/更改线 目的 14 设置一个占位符参考(cachedHealth)来跟踪角色的生命值在更改之间,以便您可以比较更改是否更低(伤害) 17 ‑ 18 在初始角色重生点时,创建一个新的 ColorCorrectionEffect 在玩家当前的 Camera 内,或在稍后的重生中获取同一实例的参考。通过将此 后期处理效果 传递到玩家的相机,仅适用于他们的本地屏镜头,不适用于服务器上每个玩家的屏幕。 68 ‑ 83 首先进行条件检查以确认健康状况变化小于 cachedHealth 值,表示损坏;如果是这样,它将 cachedHealth 设置为新值。接下来,它将 染色设置为 (红色)的更高饱和度,然后将染色返回到中性白色的默认值( )无饱和度。
如果你现在测试体验,你会注意到角色受到伤害时屏幕会短暂闪红: