在工作室中实现设计

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

实现你的设计 是在 Studio 中使用内置和自定义用户界面元素以及触发你的用户界面上下文的脚本来创建你的原型过程。教程的这一令人激动的步骤是你看到所有设计和辛苦工作结合在一起,形成一个紧密的工作流程集,完整且准备好与玩家互动。

使用 样本激光标签体验.rbxl 文件作为参考,本节用户界面设计课程的这一部分向您展示如何将您的 UI 规划付诸于实践,包括指导:

  • 从用户界面资产库中检索资产ID,以便您可以重新创建示例激光标签体验的用户界面组件。
  • 在工作室直接模拟各种设备,看看你的用户界面在不同屏幕和比例率上如何显示。
  • 创建ScreenGuiSurfaceGuiBillboardGui对象,分别显示在玩家的屏幕、零件表面和3D空间中,显示您的界面。

在你审查本节中的技巧之后,你可以将它们应用到自己的项目中,制作令玩家熟悉你的体验中可以做什么的激动人心的用户界面组件。

获取资产库

资产库是您可以添加到库存以便轻松访问和重复使用的资产集合。从 创作者商店 获取的项目资产库包含九个 2D 个人用户界面元素资产,以及你在本教程部分创建的目标、冲击波选择器和玩家信息组件的最终版本。

多重爆破器图标 rbxassetid://14309094777
>

单个爆破器图标 rbxassetid://14309094641
>

粉色团队图标 rbxassetid://14309678581
>

椭圆形 rbxassetid://14304828203
>

倒置三角形陷阱 rbxassetid://14304827304
>

绿色团队图标 rbxassetid://14309678701
>

淡化 rbxassetid://14304826876
>

多向渐变 rbxassetid://14304827147
>

爆炸按钮图标 - 默认 rbxassetid://18308375067
>

爆炸按钮图标 - 已按下 rbxassetid://18308372597
>

十字线图标 rbxassetid://14400935532
>

命中标记图标 rbxassetid://14401148777
>

六边形 rbxassetid://14462567943
>

选择箭头图标 rbxassetid://14309187282
>

边框渐变 rbxassetid://14309518632
>

您可以通过单击 Studio 中的“ 添加到库存 ”链接将图书馆的大部分添加到库存中一旦资产位于您的道具中,您可以在平台上的任何项目中重复使用它们。


要将资产库从库存导入到体验中:

  1. 在工具栏中,选择 视图 标签。

  2. 点击 工具箱 。显示 工具箱 窗口。

  3. 工具箱 窗口中,单击 库存 选项卡。显示 我的模型 排序。

  4. 点击下拉菜单,然后选择 我的包裹 排序。

  5. 单击 最终屏幕用户界面组件 瓷瓦片,然后在 Explorer 窗口中选择 已完成组件 ,然后将它们拖入 StarterGui 服务。您现在可以启用任何最终组件来引用其设计。

模拟设备

Studio 的 设备模拟器 允许您测试玩家在各种设备上如何查看和与您的 UI 互动。这个工具是实施过程中的重要部分,因为 Studio中的视窗的 aspect比不一定会反映屏幕玩家使用来访问您的体验的 aspect比,并且您的用户界面在每个设备上都要可读且可访问。

例如,如果你没有在一系列屏幕尺寸上测试你的用户界面,那么大屏幕的玩家可能无法阅读你的文本或解码你的图标,小屏幕的玩家可能无法看到 3D 空间,因为你的用户界面元素占用了太多空间显示上。

要将您的屏幕缩放到最小屏幕尺寸:

  1. 在工具栏中,选择 测试 标签。

  2. 单击 设备 。视窗会更改以反映平均笔记本电脑的比例。

    Device button indicated in Test tab
  3. 在分辨率下拉中,选择 实际分辨率 。这可以让你在模拟的设备上查看你的 UI 元素的真实解析度。

  4. 在设备下拉中,选择具有最小屏幕尺寸的设备,玩家可以使用它来访问您的体验。虽然最好的选择根据您的体验支持的设备类型不同,但示例激光标签体验测试使用 iPhone 4S 来验证用有限屏幕空间显示的用户界面。

创建屏幕用户界面对象

要在每个玩家的屏幕上显示 UI 元素,您可以在 ScreenGui 服务中创建一个 StarterGui 对象。ScreenGui 对象是屏幕上的用户界面的主要容器,而StarterGui 服务将其内容复制到每个玩家的PlayerGui 容器,当他们进入体验时。

您可以创建多个 ScreenGui 对象来组织和显示游戏过程中的 UI 元素群组。例如,示例激光标签体验包括五个独立的 对象,最初在玩家在体验主流程中遇到不同条件时禁用:

  • HUDGui - 在玩家活跃于一轮时显示体验游戏的关键信息,例如目标和每个团队的总分。
  • PickABlasterGui - 当玩家开始或重新加入回合时显示所有爆破器选择。
  • 力场图形用户界面 - 当玩家选择爆破器时显示六边形网格,而他们暂时无敌时。
  • OutStateGui - 在玩家被标记退出时,在屏幕周围显示黑暗边框。
  • 回合结果图形用户界面 - 在屏幕顶部显示带有回合结果信息的黑暗覆盖层。

在创建一个 ScreenGui 对象之后,您可以根据每个容器的目的创建并自定义其子 GuiObjects 对象。为了展示,在关注下来的即时部分中,您将学习如何为 三类信息 玩家实现用户界面元素,以便在样本激光标签体验中获得成功。 你可以调整过程的任何部分来满足自己的体验规格

要创建一个 ScreenGui 对象:

  1. 资源管理器 窗口中,将鼠标悬停在 StarterGui 服务上,然后单击 标志。将显示上下文菜单。

  2. 插入一个 ScreenGui

  3. 根据其子 UI 元素的上下文重命名 ScreenGui

  4. 重复此过程以显示每个玩家屏幕上需要显示的 UI 元素组合。

目标用户界面

设计你的布局中汲取视觉层次结构最佳实践后,本节教你如何实现与体验目标相关的所有屏幕上的用户界面元素。这组UI元素的排列在屏幕顶部附近,因为目标和每个团队的积分对于如何赢得游戏具有最重要的意义。

例如,样本提供一个客观的用户界面组件,玩家可以参考以了解他们需要做什么才能在一轮中获得成功。当玩家标记出敌方团队成员并获得积分时,该组件会在标题的提示中跟踪每个团队对整体目标的得分。要对所有客户端和服务器脚本进行高级评论,用于跟踪点数,请参阅游戏脚本教程中的跟踪点数

要准确重现示例 激光标签 体验中的目标用户界面:

  1. 为整个组件创建一个容器。

    1. 将 框架 插入 HUDGui 对象。

      1. 探索器 窗口中,导航到 StarterGui 服务。
      2. 将鼠标悬停在其子 HUDGui 对象上,然后单击 ⊕ 图标。将显示上下文菜单。
      3. 从上下文菜单中插入一个 框架
    2. 选择新的 框架 ,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0 以在框架顶部中设置框架的起始点(框架左侧到右侧的 50% 和框架顶部到底的 0%)。
      2. 背景透明 设置为1,使框架的背景完全透明。
      3. 位置 设置为 {0.5, 0},{0.03, 0} 以设置屏幕顶部中间的框架(屏幕左侧到右侧为 50%,屏幕顶部到底为 3%,以便有一点缓冲)
      4. 大小 设置为{0.5, 0},{0.13, 0},以便框架的元素占用屏幕顶部的大部分(横向 50%,垂直 13%)来吸引玩家注意力。
      5. 名称 设置为 目标
    3. (可选)UIAspectRatioConstraint 插入 目标 以确保无论玩家的屏幕尺寸如何,标签的比例仍然相同。样本将其 UIAspectRatioConstraint.AspectRatio 属性设置为 7 .

  2. 创建一个容器来容纳目标的提示对象。

    1. 框架 插入 目标 .

    2. 选择新的 框架 ,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0 以在框架顶部中设置框架的起始点(框架左侧到右侧的 50% 和框架顶部到底的 0%)。
      2. 背景透明 设置为1,使框架的背景完全透明。
      3. 位置 设置为{0.5, 0},{0, 0}以设置容器中间的框架(从左到右父框的 50%,从上到下父框的 0%)。
      4. 尺寸 设置为 {1, 0},{0.67, 0} ,以便选择的 UI 组件占用容器的大约一半以上(100% 横向和 67% 垂直的父框)
      5. 名称 设置为 目标显示
  3. 创建标题元素。

    1. 图像标签 插入 目标显示

    2. 选择 图像标签 ,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 1 以在标签底部中设置标签的起始点(标签左侧到右侧的 50% 和标签顶部到底的 100%)。
      2. 背景透明 设置为1,使标签的背景完全透明。
      3. 布局顺序 设置为-1
      4. 位置 设置为{0.5, 0},{0.34, 0},以设置框架顶部中间附近的标签(从左到右父框的 50%,从顶到底父框的 34%)。
      5. 尺寸 设置为 {0.46, 0},{0.34, 0} 以扩展提示区域几乎到父框的一半(横向 46% 和垂向 34%)。
      6. 名称 设置为头部。
      7. 图像 设置为 rbxassetid://14304828123 以显示椭圆形。
      8. 图像透明度 设置为 0.15 以使头部部分透明。
    3. (可选)UIAspectRatioConstraint 插入 图像标签 以确保标签的比例率不管玩家的屏幕大小都保持相同。样本将其 UIAspectRatioConstraint.AspectRatio 属性设置为 13.781 .

    4. 文本标签 插入 标题 以显示标题。

    5. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在自身中间设置新标签的起始点(标签左右的 50% 从左到右,标签顶部到底的 50%)。
      2. 背景透明 设置为1,使标签的背景完全透明。
      3. 位置 设置为{0.5, 0},{0.5, 0}将标签移至父标签的中间(父标签左侧到右侧的50%,父标签顶部到底部的50%)。
      4. 尺寸 设置为 {0.62, 0},{0.55, 0} 以扩展文本空间到父标签的一半以上(横向 62% 和垂向 55% 的父标签)。
      5. 名称 设置为 头部文本标签
      6. 字体面 设置为 蒙特塞拉特 以适应未来主义的审美。
      7. 重量 设置为 中等 以加粗字体。
      8. 文本 设置为 目标 .
      9. 启用 文本缩放
  4. 创建提示元素。

    1. 图像标签 插入 目标显示

    2. 选择 图像标签 ,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 1 以在标签底部中设置标签的起始点(标签左侧到右侧的 50% 和标签顶部到底的 100%)。
      2. 背景透明 设置为1,使标签的背景完全透明。
      3. 位置 设置为{0.5, 0},{1, 0}将标签移至父框的左中间(父框左侧的 50% 到右侧,父框顶部的 100%)。
      4. 尺寸 设置为 {0.89, 0},{0.66, 0} 以扩展文本空间到几乎与父框的全宽(横向 89% 和垂向 66% 的父框)。
      5. 名称 设置为 身体
      6. 图像 设置为 rbxassetid://14304827265 以显示上下颠倒的三角形。
      7. 图像颜色3 设置为 0, 0, 0 以将图像涂黑。
      8. 图像透明度 设置为 0.3 以使头部部分透明。
    3. (可选)UIAspectRatioConstraint 插入 图像标签 以确保标签的比例率不管玩家的屏幕大小都保持相同。样本将其 UIAspectRatioConstraint.AspectRatio 属性设置为 13.781 .

    4. 文本标签 插入 身体 以显示提示。

    5. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在自身中间设置新标签的起始点(标签左右的 50% 从左到右,标签顶部到底的 50%)。
      2. 背景透明 设置为1,使标签的背景完全透明。
      3. 位置 设置为{0.5, 0},{0.5, 0}将标签移至父标签的中间(父标签左侧到右侧的50%,父标签顶部到底部的50%)。
      4. 尺寸 设置为 {0.85, 0},{0.39, 0} 以扩展文本空间到父标签的一半以上(父标签的横向 85% 和垂直 39%)。
      5. 名称 设置为 BodyTextLabel
      6. 字体面 设置为 蒙特塞拉特 以适应未来主义的审美。
      7. 重量 设置为 中等 以加粗字体。
      8. TextColor3 设置为 255, 255, 255 使文本对黑暗背景白色。
      9. 文本 设置为 标签反对玩家得分!第一支得到 %d 分的团队获胜。 .
      10. 启用 文本缩放
  5. 创建一个容器来容纳目标的团队计数器。

    1. 框架 插入 目标 .

    2. 选择新的 框架 ,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 1 以在自身底部中设置标签的起始点(左到右框架的 50%,右到左框架的 100%)。
      2. 背景透明 设置为1,使框架的背景完全透明。
      3. 位置 设置为{0.5, 0},{1, 0}将框架设置在容器的底部中间(从左到右的父框的左侧为 50%,从顶到底的父框为 100%)。
      4. 尺寸 设置为 {0.44, 0},{0.27, 0} ,以便选择的 UI 组件占左到右容器的约一半(横向 44% 和垂直 27% 的父框)
      5. 名称 设置为 TeamPointCounter
  6. 为团队计数器创建缓冲。

    1. 从步骤 5 中插入 UIListLayout 对象到框架。
    2. 选择 UIListLayout 对象,然后在 属性窗口 中,
      1. 填充 设置为 0.025, 0 以在未来的团队计数器之间提供空间
      2. 填充方向 设置为 横向 ,以便每个团队的计数器旁边显示。
      3. 水平对齐 设置为 中心 ,每个团队的计数器都对齐到对方中间。
  7. 创建绿色团队计数元素。

    1. 图像标签 插入 团队点数计数器

    2. 选择 图像标签 ,然后在 属性 窗口中,

      1. 背景透明 设置为1,使标签的背景完全透明。
      2. 位置 设置为{0.5, 0},{1, 0}将标签移至父框的左中间(父框左侧的 50% 到右侧,父框顶部的 100%)。
      3. 尺寸 设置为 {0.5, 0},{1, 0} 以将标签扩展到父框的宽度的一半(50% 垂直向上,100% 向下)。
      4. 名称 设置为 TeamACounter
      5. 图像 设置为 rbxassetid://14304826831 以显示方向渐变。
      6. 图像颜色3 设置为 88, 218, 171 以淡化图像的绿色。
    3. 配置一个自定义属性来跟踪这个标签是为绿团队的。

      1. 属性 窗口中,导航到 属性 部分,然后单击加号符标志。弹出对话框显示。
      2. 名称 字段中,输入 团队颜色
      3. 类型 下拉菜单中,选择 BrickColor
      4. 点击 保存 按钮。
      5. 将新的 团队颜色 属性设置为 薄荷
    4. 文本标签 插入 TeamACounter 以显示提示。

    5. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 1, 0.5 以在右中设置新标签的起始点(标签左至右的 100%,标签顶部至底部的 50%)。
      2. 背景透明 设置为1,使标签的背景完全透明。
      3. 位置 设置为{0.95, 0},{0.5, 0}将标签移至父标签右侧(从左到右的父标签95%,从顶到底的父标签50%)。
      4. 尺寸 设置为 {0.85, 0},{0.39, 0} 以扩展文本空间到父标签的一半以上(父标签的横向 85% 和垂直 39%)。
      5. 字体面 设置为 蒙特塞拉特 以适应未来主义的审美。
      6. 重量 设置为 粗体 以加粗字体。
      7. TextColor3 设置为 255, 255, 255 使文本对黑暗背景白色。
      8. 文本 设置为 -
      9. 启用 文本缩放
      10. TextXAlignment 设置为 向右
    6. UIStroke 对象插入到 文本标签 中,然后在 属性窗口 中将 颜色 设置为 8, 78, 52 以用深绿色突线描述文本。

  8. 创建粉色团队计数元素。

    1. 复制 团队AICounter 和其子女。

    2. 选择重复的 TeamACounter ,然后在 属性窗口 中,

      1. 名称 设置为 TeamBCounter
      2. 图像 设置为 rbxassetid://14305849451 以显示相反方向的渐变。
      3. 图像颜色3 设置为 255, 170, 255 来染色图像玫瑰粉。
      4. 团队颜色 属性设置为 玫瑰粉色
    3. 选择 TeamBCounter 的重复子 文本标签 ,然后在 属性窗口 中,

      1. 锚点 设置为 0, 0.5 以在左中设置新标签的起始点(从左到右标签的左到右为 0%,从顶到底标签的左到右为 50%)。
      2. 位置 设置为{0.05, 0},{0.5, 0}将标签移至父标签左侧(从左到右父标签的 5%,从顶到底父标签的 50%)。
      3. TextXAlignment 设置为 左侧
    4. 选择 TeamBCounter 的重复 UIStroke 子,然后在 属性窗口 中将 颜色 设置为 158, 18, 94 以用深粉色的线条画出轮廓。

  9. 在示例 ReplicatedStorage 位置文件中参考以下 脚本,它们可以编程地更新目标提示和跟踪团队点数。

以下脚本需要一组模块脚本,共同设置主显示头(HUD),包括 setObjectivestartSyncingTeamPoints 。玩家加入回合并选择爆破器后,该脚本确保所有 HUD 用户界面元素都适当显示玩家的状态、设备和团队状态。


local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)

爆破器用户界面

设计你的布局中继承视觉层次最佳实践,本节教你如何实现与玩家发射器相关的所有屏幕上的用户界面元素。这组UI元素的排列占据屏幕空间的大部分,因为它作为聚焦点吸引玩家注意力于3D空间的行动,并且对于游戏的玩法具有最重要的意义。

十字线

十字线是一个用于向玩家通知他们武器爆炸时将产生影响的 UI 元素。这个用户界面元素对第一人称射击体验至关重要,因为玩家需要能够准确瞄准他们的冲击波并标记敌方团队成员。

与第一人称主题击游戏中的其他体验类似,样本激光标签体验将准星放置在屏幕中心,因此玩家在移动虚拟形象通过 3D 空间时有什么静止的东西可以专注。除了减少运动恶心外,这种布置还允许十字线在融入整体环境的同时被感知。

要准确重现样本 激光标签 体验中的十字线:

  1. 将 图像标签 插入到 HUDGui 对象中。

    1. 探索器 窗口中,导航到 StarterGui 服务。

    2. 将鼠标悬停在其子对象 HUDGui 上,然后单击 标志。将显示上下文菜单。

    3. 从上下文菜单中插入一个 图像标签

  2. 选择新的 图像标签 ,然后在 属性窗口 中,

    1. 图像 设置为rbxassetid://14400935446
    2. 锚点 设置为 0.5, 0.5 以在标签中设置标签的起始点(标签左右的 50% 和标签顶部到底的 50%)。
    3. 背景透明 设置为1,使标签的背景完全透明。
    4. 名称 设置为 十字线
    5. 位置 设置为 {0.5,0},{0.5,0} 以设置屏幕中间的标签。
    6. 缩放类型 设置为 适合 以便图像适合其容器并且不会在各种屏幕尺寸上伸展。
  3. (可选)UIAspectRatioConstraint 插入 十字线 以确保标签的比例仍然不管玩家的屏幕大小保持一致。样本将其 UIAspectRatioConstraint.AspectRatio 属性设置为 0.895 .

命中标记

命中标记是一个仅在爆炸对敌团队的另一名玩家造成影响时显示的 UI 元素。像准星一样,这个用户界面元素对第一人称射击体验至关重要,因为它提供了玩家标记敌人成功时的视觉反馈。

要准确重现样本 激光标签 体验中的命中标记:

  1. 将 图像标签 插入 十字线 对象。

    1. 探索器 窗口中,导航到 StarterGui 服务。

    2. 将鼠标悬停在其子对象 十字线 上,然后单击 标志。一个上下文菜单显示。

    3. 从上下文菜单中插入一个 图像标签

  2. 选择新的 图像标签 ,然后在 属性窗口 中,

    1. 图像 设置为 rbxassetid://14401148736 以显示长方形命中标记标志。
    2. 锚点 设置为 0.5, 0.5 以在标签中设置标签的起始点在标签中间。
    3. 背景透明 设置为1,使标签的背景完全透明。
    4. 位置 设置为 {0.5,0},{0.5,0} 以设置屏幕中间的标签。
    5. 名称 设置为 命中标记
    6. 尺寸 设置为 {0.6, 0},{0.06, 0} 以减少十字线周围的长方形的尺寸。
    7. 图像透明度 设置为 1 以使命中标记完全透明。在下一步中的脚本每次玩家的爆炸都会将透明度返回为 0,每次击中敌团队另一名玩家时。
  3. 在示例 激光标签 位置文件中引用以下 脚本,该脚本会在爆炸与敌团队玩家发生碰撞时显示命中标记。

以下脚本需要一组模块脚本,它们共同工作以设置主显示头(HUD),包括 setupHitmarker。玩家加入回合并选择爆破器后,该脚本确保所有 HUD 用户界面元素都适当显示玩家的状态、设备和团队状态。


local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)

冲击波选择器

爆破器选择器是玩家使用的界面组件,用于在加入或重新加入回合之前选择爆破器类型。样本激光标签体验提供两种类型的爆破器:一个产生宽、横向分布的多个射线,另一个产生单个射线。玩家选择的爆破器类型会在回合期间影响他们的战略,使这个 UI 组件成为整个体验的必要工作流程。

以下步骤详细说明如何创建多个容器用于不同的用户界面元素组合、带有提示的头部、导航和选择按钮以及爆破按钮预制件。对整个组件的脚本逻辑将不同的视觉特征填充到爆破按钮预制件中,根据 Configuration 代表每种爆破类输入的实例。

这种设置允许您创建额外的 Configuration 实例,用于更多爆破类型,它们会自动在爆破选择器中正确显示,无需在 StarterGui.PickABlasterGui 内创建单个按钮。

要准确重现样本 激光标签 体验中的冲击波选择器:

  1. 为整个组件创建一个容器。

    1. 将 框架 插入 PickABlaster 对象。

      1. 探索器 窗口中,导航到 StarterGui 服务。
      2. 将鼠标悬停在其子对象 PickABlaster 上,然后单击 标志。将显示上下文菜单。
      3. 从上下文菜单中插入一个 框架
    2. 选择新框架,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 1 以在框架的底部中设置框架的起始点(左到右框架的 50%,右到左框架的 100%)。
      2. 背景透明 设置为1,使框架的背景完全透明。
      3. 位置 设置为{0.5, 0},{0.9, 0},将框架设置在屏幕的底中(屏幕左侧到右侧的 50%,屏幕顶部到底的 92.4%)。
      4. 尺寸 设置为 {0.8, 0},{0.25, 0} 以便爆破器选择器的用户界面组件占用大部分屏幕来吸引玩家注意力(横向 80%,垂直 25%)。
      5. 名称 设置为 组件
    3. (可选)UIAspectRatioConstraint 插入 组件 以确保无论玩家屏幕大小如何,框架和其子元素的比例仍然相同。样本将其 UIAspectRatioConstraint.AspectRatio 属性设置为 5

  2. 创建一个容器来容纳 UI 元素组合。

    1. 框架 插入 组件

    2. 选择新框架,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在框架中间设置框架的起始点(从左到右框架的左侧 50%,从顶到底框架的顶部 50%)。
      2. 背景透明 设置为1,使框架的背景完全透明。
      3. 位置 设置为 {0.5, 0},{0.375, 0} 以设置容器顶部中间的框架(从左到右父框的 50%,从顶到底父框的 37.5%)
      4. 尺寸 设置为 {1, 0},{0.75, 0} 以便选择的 UI 组件占用容器的 3/4 (父框的 100% 横向和 75% 垂直)。
      5. 名称 设置为 选择框 .
  3. 创建一个提示给爆破器选择器。

    1. 图像标签 插入 选择框 .

    2. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 1 以在标签底部中设置标签的起始点(标签左侧到右侧的 50% 和标签顶部到底的 100%)。
      2. 背景透明 设置为1,使标签的背景完全透明。
      3. 布局顺序 设置为-1
      4. 位置 设置为{0.5, 0},{0.22, 0},以设置框架顶部中间附近的标签(从左到右父框的 50%,从顶到底父框的 22%)。
      5. 尺寸 设置为 {0.45, 0},{0.22, 0} 以扩大提示区到几乎是框架的一半(横向 45% 和垂向 22% 的父框)。
      6. 名称 设置为 头部
      7. 图像 设置为 rbxassetid://14304828123 以显示椭圆形。
      8. 图像透明度 设置为 0.15 以使头部部分透明。
    3. (可选)UIAspectRatioConstraint 插入标签以确保标签的比例率无论玩家的屏幕尺寸如何都不会改变。样本将其 UIAspectRatioConstraint.AspectRatio 属性设置为 13.78 .

    4. 文本标签 插入 头部 以显示提示。

    5. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在自身中间设置新标签的起始点(标签左右的 50% 从左到右,标签顶部到底的 50%)。
      2. 背景透明 设置为1,使标签的背景完全透明。
      3. 位置 设置为{0.5, 0},{0.5, 0}将标签移至父标签的中间(父标签左侧到右侧的50%,父标签顶部到底部的50%)。
      4. 尺寸 设置为 {0.6, 0},{0.55, 0} 以扩展文本空间到父标签的一半以上(父标签的 60% 横向和 55% 垂直)。
      5. 名称 设置为 头部文本标签
      6. 字体面 设置为 蒙特塞拉特 以适应未来主义的审美。
      7. 重量 设置为 中等 以加粗字体。
      8. 文本 设置为 选择爆破器
      9. 启用 文本缩放
  4. 创建容器用于您的爆破按钮容器和选择箭头。

    1. 图像标签 插入 选择框 .

    2. 选择新标签,然后在 属性 窗口中,

      1. 移除默认 图像 值。
      2. 锚点 设置为 0.5, 1 以在标签底部中设置标签的起始点(标签左侧到右侧的 50% 和标签顶部到底的 100%)。
      3. 背景颜色 设置为0, 0, 0,使标签变黑。
      4. 背景透明 设置为0.3,将标签的不透明度降低 30%,并与体验中的所有黑色用户界面元素匹配。
      5. 位置 设置为{0.5, 0},{1, 0}将标签设置为框架的底部中间(从左到右的父框的左侧为 50%,从顶到底的父框为 100%)。
      6. 尺寸 设置为 {1, 0},{0.77, 0} 以扩展标签区到提示下方的空间(横向 100% 和垂向 77% 的父框)
    3. 圆化容器的角。

      1. UICorner 对象插入标签。
      2. 选择新的角对象,然后在 属性 窗口中将 角度半径 设置为 0.075, 0 以圆化角落。
  5. 创建一个容器来容纳你的爆破按钮。

    1. 从步骤 4 中插入 框架 到标签。

    2. 选择新框架,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在框中间设置新框的起始点(从框左到框右的 50% 和从框顶到框底的 50%)。
      2. 背景透明 设置为1,使框架的背景完全透明。
      3. 位置 设置为{0.5, 0},{0.5, 0}以设置父标签中间的框架(从左到右父框的50%和父框的顶部到底的50%)。
      4. 大小 设置为{0.85, 0},{0.77, 0}以扩大框架区域到标签的大部分(横向 85% 和垂直 77% 的父标签)。
      5. 名称 设置为 容器
  6. 为所有未来的爆破按钮创建缓冲。

    1. 从步骤 5 中插入 UIListLayout 对象到框架。
    2. 选择新布局对象,然后在 属性 窗口中,
      1. 填充 设置为 0.035, 0 以提供所有未来按钮之间的空间。
      2. 填充方向 设置为 横向 ,每个按钮都可以旁边显示。
      3. 水平对齐垂直对齐 设置为 中心 ,每个按钮都会对齐到另一个按钮的中间。
  7. 创建左导航按钮。

    1. 从步骤 4 中插入一个 图像按钮 对象到 图像标签

    2. 选择新按钮,然后在 属性 窗口中,

      1. 移除默认 图像 值。
      2. 锚点 设置为 0, 0.5 以在左中设置新按钮的起始点(从左到右按钮左侧为 0%,从顶到底按钮左侧为 50%)。
      3. 背景透明度 设置为 0.15 以提供选择按钮时的视觉反馈。
      4. 位置 设置为{0.02, 0},{0.5, 0},为按钮的左侧提供填充,从其父容器左侧到右侧为 2%,从父标签顶部到底部为 50%。
      5. 尺寸 设置为 {0.04, 0},{0.33, 0} 以使选择按钮比爆破器按钮小得多(横向 4% 和垂直 33% 的父框)
      6. 名称 设置为 导航按钮左侧 .
    3. 圆化按钮的角落。

      1. UICorner 对象插入按钮。
      2. 选择新的角对象,然后在 属性 窗口中将 角度半径 设置为 0.1, 0 以圆化角落。
    4. 图像标签 对象插入按钮。

    5. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在自身中间设置新标签的起始点(标签左右的 50% 从左到右,标签顶部到底的 50%)。
      2. 位置 设置为{0.45, 0},{0.5, 0},以设置标签靠近其父按钮的中间(从左到右父按钮的左侧 45%,从上到下父按钮的顶部 50%)。这个值不在中间,因为箭头不会视觉上看起来像按钮的中间部分在{0.5, 0},{0.5, 0}
      3. 尺寸 设置为 {0.8, 0},{0.8, 0} 以扩展标签区到提示下的空间(横向 80% 和垂直 80% 的父框)。
      4. 背景透明度 设置为 1 以使图像的背景完全透明。
      5. 图像 设置为rbxassetid://14309187238
      6. 缩放类型 设置为 适合 .
  8. 创建正确的导航按钮。

    1. 复制 导航按钮左

    2. 选择重复按钮,然后在 属性 窗口中,

      1. 锚点 设置为 1, 0.5 以在右中设置新按钮的起始点(按钮左至右的 100%,按钮顶至底的 50%)。
      2. 位置 设置为 {0.98, 0},{0.5, 0} 以向按钮的右侧提供垫料(从父容器左侧到右侧为 98%,从父标签顶部到底部为 50%)。
      3. 名称 设置为 导航按钮右侧 .
    3. 选择其 图像标签 子对象。

      1. 旋转 设置为 180 以翻转图像。
      2. 位置 设置为{0.55, 0},{0.5, 0},以设置标签靠近其父按钮的中间(从左到右父按钮的 55%,从上到下父按钮的 50%)。这个值不在中间,因为箭头不会视觉上看起来像按钮的中间部分在{0.5, 0},{0.5, 0}
  9. 创建 选择 按钮。

    1. 图像按钮 插入 组件 。注意这个过程如何将选择按钮与 选择框 分开,以便您可以在组件的主部分与选择按钮之间添加 padding。

    2. 选择新按钮,然后在 属性 窗口中,

      1. 移除默认 图像 值。
      2. 锚点 设置为 0.5, 1 以在自身底部中设置新按钮的起始点(按钮左右的 50% 和按钮顶部到底的 100%)。
      3. 背景透明度 设置为 0.15 以提供选择按钮时的视觉反馈。
      4. 位置 设置为 {0.5, 0},{0.99, 0} 以设置容器的底部中间附近的按钮(从左到右的父框的左侧为 50%,从顶到底的父框的顶部为 99%)
      5. 尺寸 设置为 {0.17, 0},{0.18, 0} 以延长爆破器按钮下方的按钮长度(横向 17% 和垂直 18% 的父框)。
      6. 名称 设置为 选择按钮
    3. 圆化按钮的角落。

      1. UICorner 对象插入按钮。
      2. 选择新的角对象,然后在 属性 窗口中将 角度半径 设置为 0.2, 0 以圆化角落。
    4. 文本标签 对象插入到按钮中,以便您可以显示行动呼动作。

    5. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在自身中间设置新标签的起始点(标签左右的 50% 从左到右,标签顶部到底的 50%)。
      2. 背景透明 设置为1,使标签的背景完全透明。
      3. 位置 设置为{0.5, 0},{0.5, 0}将标签移至按钮中间(从左到右父按钮的 50%,从上到下父按钮的 50%)。
      4. 尺寸 设置为 {0.9, 0},{0.55, 0} 以扩展文本空间到父标签的几乎全部宽度(90% 横向和 55% 垂直于父标签)。
      5. 名称 设置为 SelectTextLabel
      6. 字体面 设置为 蒙特塞拉特 以适应未来主义的审美。
      7. 重量 设置为 中等 以加粗字体。
      8. 文本 设置为 选择
      9. 启用 文本缩放
  10. 创建爆破按钮预制件。

    1. 复制存储服务 中,创建文件夹结构来组织您的 UI 对象。样本使用一个 实例 文件夹与一个子 Guis 文件夹。
    2. 图像按钮 对象插入 Guis 文件夹。
    3. 选择新按钮,然后在 属性 窗口中,
      1. 移除默认 图像 值。
      2. 锚点 设置为 0.5, 0.5 以在按钮中间设置新按钮的起始点(按钮左右的 50% 和按钮顶部到底的 50%)。
      3. 背景透明 设置为0.65,提供视觉反馈,即按钮不在焦点上。步骤 12 中的脚本在按钮处于焦点时提供程序化视觉反馈。
      4. 布局顺序 设置为2
      5. 名称 设置为 BlasterButtonPrefab
      6. 大小 设置为{0.8, 0},{0.8, 0}
      7. 图像透明度 设置为 1 以使图像完全透明。
    4. UIAspectRatioConstraint 插入 BlasterButtonPrefab 以确保按钮的比例率在组件内无论玩家的屏幕尺寸如何都保持相同。
    5. 圆化按钮的角落。
      1. UICorner 对象插入 BlasterButtonPrefab
      2. 选择 UICorner ,然后在 属性 窗口中将 角度半径 设置为0.05, 0来圆角。
    6. 图像标签 插入 BlasterButtonPrefab
    7. 选择新标签,然后在 属性 窗口中,
      1. 移除默认 图像 值。
      2. 锚点 设置为 0.5, 0.5 以在自身中间设置新标签的起始点(标签左右的 50% 从左到右,标签顶部到底的 50%)。
      3. 背景透明 设置为1,使标签的背景完全透明。
      4. 位置 设置为{0.52, 0},{0.497, 0},以设置标签靠近其父按钮的中间(从左到右父按钮的 52%,从上到下父按钮的 49.7%)。这个值不在中间,因为爆破器看起来不像按钮的中间在 。
      5. 尺寸 设置为 {1.20, 0},{0.9, 0} 以扩展按钮外的标签区(横向 120% 和垂直 90% 的父按钮)。
      6. 缩放类型 设置为 适合 .
  11. 在示例 激光标签 位置文件中引用以下 脚本,显示每个激光发射器的按钮,当玩家选择一个不在焦点上的按钮时缩放按钮,并将玩家的激光选择附加到他们的虚拟形象。

以下脚本需要一组脚本,共同工作以创建爆破选择器。当玩家加入体验或在生命值达到零后重生回一轮时,该脚本激活所有爆破器选择器的用户界面元素,直到玩家做出选择。


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GuiAttribute = require(ReplicatedStorage.GuiAttribute)
local setupBlasterButtons = require(script.setupBlasterButtons)
local connectResetSelectionOnEnabled = require(script.connectResetSelectionOnEnabled)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("PickABlasterGui")
setupBlasterButtons(gui)
connectResetSelectionOnEnabled(gui)
gui:SetAttribute(GuiAttribute.selectedIndex, 1)

爆破按钮

爆炸按钮是玩家使用来爆炸他们的爆炸器的界面组件,如果他们通过移动设备或平板电脑访问体验。示例激光标签体验使用具有图标的爆破按钮来传达按钮的功能,而不需要文本。

要准确重现样本 激光标签 体验中的爆炸按钮:

  1. 将 图像按钮 插入到 HUDGui 对象中。

    1. 探索器 窗口中,导航到 StarterGui 服务。

    2. 将鼠标悬停在其子对象 HUDGui 上,然后单击 标志。将显示上下文菜单。

    3. 从上下文菜单中插入一个 图像按钮

  2. 在视图中,将按钮移至玩家的拇指自然休息的位置,然后在 属性 窗设备中,

    1. 图像 设置为 rbxassetid://18308375035 以显示爆炸按钮标志。
    2. 压缩图像 设置为 rbxassetid://18308372558 显示玩家按下按钮时反转的爆炸按钮图标。
    3. 背景透明 设置为1,使标签的背景完全透明。
    4. 名称 设置为 爆炸按钮
    5. 缩放类型 设置为 适合 以便图像适合其容器并且不会在各种屏幕尺寸上伸展。
    6. 图像透明度 设置为0.3以减少标签的不透明度,使其与体验中的所有黑色用户界面元素匹配。
  3. UIAspectRatioConstraint 插入 爆炸按钮 以确保按钮的比例率不论玩家的屏幕大小都保持相同。

  4. 在示例 激光标签 位置文件中,参考以下 脚本,该脚本会在玩家使用触摸输入控制备时显示激光发射按钮。

以下脚本需要一组模块脚本,它们共同工作以设置主显示头(HUD),包括 setupTouchButtonAsync。玩家加入回合并选择爆破器后,该脚本确保所有 HUD 用户界面元素都适当显示玩家的状态、设备和团队状态。


local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)

玩家界面

设计你的布局中汲取视觉层次结构最佳实践后,本节教你如何实现与玩家状态相关的所有屏幕上的用户界面元素。这组UI元素的排列在屏幕边缘附近,因为玩家可以在没有分散注意力的情况下理解这些周边信息。

玩家指示器

玩家指示器是玩家快速解读他们所属团队的界面组件,当他们生成到自己团队的生成区时,他们会快速解读自己所属的团队。样本激光标签体验提供两个版本的玩家指示器,取决于玩家是在 绿色粉色 团队上。

绿色团队
>

粉色团队
>

遵循 选择颜色主题 的指导,玩家指示器的两个版本都将团队颜色与具有最小细节的独特、简单的图标结合,以便它们在小屏幕上仍然可读。提供两种视觉反馈形式很重要,因为它有助于保持设计对色盲玩家的可访问性。

要准确重现样本 激光标签 体验中的玩家指示器组件:

  1. 将 框架 插入 HUDGui 对象。

    1. 探索器 窗口中,导航到 StarterGui 服务。
    2. 将鼠标悬停在其子 HUDGui 对象上,然后单击 ⊕ 图标。将显示上下文菜单。
    3. 从上下文菜单中插入一个 框架
  2. 选择新的 框架 ,然后在 属性 窗口中,

    1. 锚点 设置为 0, 1 以在框架的底部中设置框架的起始点(从左到右框架的左侧为 0%,从顶部到底为框架的 100%)。

    2. 背景透明 设置为1,使标签的背景完全透明。

    3. 名称 设置为 PlayerDisplay

    4. 位置 设置为 {0.02, 0},{0.97, 0} 以设置屏幕左下角附近的框架。

    5. 尺寸 设置为 {0.23, 0},{0.08, 0} 以缩短和扩展框架。

    6. 启用 片段子孙 将孩子图形用户界面扩展到框架之外的内容进行裁剪。

  3. 创建多边形状。

    1. 图像标签 插入 玩家显示

    2. 选择新标签,然后在 属性 窗口中,

      1. 图像 设置为 rbxassetid://14304828123 以显示楔形标志。
      2. 锚点 设置为 1, 1 以在右下角设置标签的起始点(标签左至右的 100%,标签顶至底的 100%)。
      3. 背景透明 设置为1,使标签的背景完全透明。
      4. 名称 设置为
      5. 位置 设置为{1,0},{1,0}将标签设置为框架右侧。
      6. 大小 设置为{1.858, 0},{0.581, 0}以扩展框架外的标签,并将其缩短到框架长度的一半以下。
      7. 图像透明度 设置为 0.15 以使标签略透明。
      8. 缩放类型 设置为 适合 以便图像适合其容器并且不会在各种屏幕尺寸上伸展。
      1. UIAspectRatioConstraint 插入 以确保标签和其子元素的 UI 比例率无论玩家屏幕大小如何都保持相同。
      2. 选择新约束,然后在 属性窗口 中将 比例率 设置为 13.78
  4. 创建玩家的竖向像盒。

    1. 图像标签 插入 玩家显示

    2. 选择新标签,然后在 属性 窗口中,

      1. 图像 属性中删除 placeholder 资产ID。在步骤 7 中,脚本通过编程插入玩家的肖像到图像标签。
      2. 锚点 设置为 0, 1 以在左下角设置标签的起始点(从标签左至右为 0%,从标签顶至底为 100%)。
      3. 背景颜色3 设置为 0, 0, 0 以将标签的背景颜色设置为黑色。
      4. 背景透明 设置为0.3,将标签的不透明度降低 30%,并与体验中的所有黑色用户界面元素匹配。
      5. 名称 设置为 PlayerPortrait
      6. 位置 设置为{0.11, 0},{1, 0}将标签设置为多边形形状的左侧。
      7. 大小 设置为{0.23, 0},{1, 0}以缩小标签。
      8. 图像透明度 设置为 0.15 以使标签略透明。
      9. 缩放类型 设置为 适合 以便图像适合其容器并且不会在各种屏幕尺寸上伸展。
      1. UIAspectRatioConstraint 插入 PlayerPortrait 以确保标签和其子元素的 UI 比例无论玩家屏幕大小如何都保持相同。
      2. UICorner 插入 PlayerPortrait ,然后在 属性窗口 中将 角度半径 设置为 0.05, 0 以稍微圆化角落。
  5. 创建玩家名称的文本标签。

    1. 文本标签 对象插入 玩家显示

    2. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0, 0.5 以在左中设置新按钮的起始点(从左到右按钮左侧为 0%,从顶到底按钮左侧为 50%)。
      2. 背景透明 设置为1,使标签的背景完全透明。
      3. 名称 设置为 PlayerNameTextLabel
      4. 位置 设置为{0.35, 0},{0.72, 0}将标签设置为容器右侧(从左到右的父标签的 35%,从上到下的父标签的 72%)。
      5. 尺寸 设置为 {0.52, 0},{0.3, 0} 以便文本占用大部分的多边形形状区域(横向 52% 和垂向 30% 的父框)
      6. 字体面 设置为 蒙特塞拉特 以适应未来主义的审美。
      7. 重量 设置为 粗体 以加粗字体。
      8. 文本 属性内移除占位符文本。第 7 步的脚本通过编程将玩家的名称插入到文本标签中。
      9. 启用 文本缩放
      10. TextXAlignment 设置为 左侧
  6. 创建显示在玩家竖向像左侧的团队图标和颜色。

    1. 文件夹 插入 PlayerDisplay ,然后重命名为 团队图标 .

    2. 创建 绿色 团队图标和颜色。

      1. 图像标签 插入 团队图标
      2. 选择新标签,然后在 属性 窗口中,
        1. 锚点 设置为 0, 1 以在左下角设置标签的起始点(从标签左至右为 0%,从标签顶至底为 100%)。
        2. 背景颜色3 设置为 88, 218, 171 将标签的背景颜色设置为薄荷绿。
        3. 名称 设置为 TeamAIcon
        4. 位置 设置为{0, 0},{1, 0}将标签设置为框架左侧。
        5. 尺寸 设置为 {0.135, 0},{0.58, 0} 以缩小标签到玩家竖向像左侧
        6. 图像透明度 设置为 1 以使标签透明。
      1. 配置一个自定义属性来跟踪这个标签是为绿团队的。这一步对步骤 7 中的脚本非常重要。
        1. 属性 窗口中,导航到 属性 部分,然后单击加号符标志。弹出对话框显示。
        2. 名称 字段中,输入 团队颜色
        3. 类型 下拉菜单中,选择 BrickColor
        4. 点击 保存 按钮。
        5. 将新的 团队颜色 属性设置为 薄荷
      2. UIAspectRatioConstraint 插入 TeamAIcon 以确保标签和其子元素的 UI 比例无论玩家的屏幕大小都保持相同。
      3. 创建标志。
        1. 图像标签 插入 TeamAIcon
        2. 选择新标签,然后在 属性 窗口中,
          1. 图像 设置为 rbxassetid://14309678670 显示绿色团队标志。
          2. 锚点 设置为 0.5, 0.5 以在标签中间设置标签的起始点(标签左侧到右侧的 50%,标签顶部到底部的 50%)。
          3. 背景透明 设置为1,使标签的背景完全透明。
          4. 名称 设置为 图标
          5. 位置 设置为{0.5, 0},{0.5, 0}将标签设置为其父标签的中间。
          6. 大小 设置为{0.7, 0},{0.6, 0}以缩小标签。
          7. 缩放类型 设置为 适合 以便图像适合其容器并且不会在各种屏幕尺寸上伸展。
    3. 创建 粉红色 团队图标和颜色。

      1. 复制 TeamAIcon 和其子团队。
      2. 选择重复的 TeamAIcon ,然后在 属性窗口 中,
        1. 背景颜色3 设置为 255, 170, 255 以将标签的背景颜色设置为玫瑰粉。
        2. 名称 设置为 TeamBIcon
        3. 团队颜色 属性设置为 玫瑰粉色
        4. 选择 团队图标 的重复孩子 TeamBIcon ,然后在 属性 窗口中将 图像 设置为rbxassetid://14309678549
  7. 在示例 激光标签 位置文件中引用以下 脚本,显示玩家指示器以适当的团队颜色和图标,当玩家在回合中活跃时。

以下脚本需要一组模块脚本,共同设置主显示头(HUD),包括startSyncingTeamColorsetPlayerNamesetPlayerPortrait。玩家加入回合并选择爆破器后,该脚本确保所有 HUD 用户界面元素都适当显示玩家的状态、设备和团队状态。


local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)

力场屏幕

力场屏幕是一个用于覆盖视窗以向玩家通知他们在加入或重新加入回合时免受敌队射击的 UI 元素。遵循 从选择艺术风格 的图标审美指南后,示例激光标签体验使用半透明六边形模式来象征力场。这个设计决定不仅强化了体验中所有 UI 的未来主义风格,还通过无文本或额外指南传达玩家的状态。

要准确重现示例 激光标签 体验中的力场屏幕:

  1. 将 图像标签 插入 ForceFieldGui 对象。

    1. 探索器 窗口中,导航到 StarterGui 服务。

    2. 将鼠标悬停在其子对象 ForceFieldGui 上,然后单击 标志。将显示上下文菜单。

    3. 从上下文菜单中插入一个 图像标签

  2. 选择新标签,然后在 属性 窗口中,

    1. 图像 设置为rbxassetid://14462567888

    2. 背景透明 设置为0.8以使力场变得透明。

    3. 尺寸 设置为 {1, 0},{1, 0} 以使图像填充整个屏幕(100% 横向和 100% 垂直于父屏幕的 GUI)

    4. 缩放类型 设置为 地砖 以在整个屏幕上制作六边形地砖。

    5. 瓷砖尺寸 设置为 {0, 104},{0, 180}

  3. UIGradient 对象插入标签。

  4. 选择新的渐变对象,然后在 属性 窗口中,

    1. 颜色 设置为一个由蓝色开始、变白,然后再次变蓝的颜色序列

      1. 颜色 设置为120, 192, 250,以将浅蓝色调色应用于所有六边形。

      2. 单击 颜色 属性,然后单击 按钮。显示颜色序列弹出窗口。

        每个三角形在颜色序列的底轴上是决定图像左到右那一点的属性颜色值的钥匙点。

      3. 单击并拖动颜色序列直到您达到 时间 值为 0.05 ,然后单击 颜色 旁边的小广场以打开 颜色 弹出窗口。

      4. 选择亮白色,然后关闭弹出窗口。

      5. 点击并拖动颜色序列直到你达到 时间 值为0.95,然后再次打开 颜色 弹出窗口,选择与之前相同的白色。

    2. 旋转 设置为225,以在左上角和右下角显示您颜色序列的蓝色部分。

    3. 透明 设置为一个数字序列,使力场看起来像闪烁。

      1. 单击 透明 属性,然后单击 按钮。一个数字序列弹出显示。数字序列的开始和结束每个方块是决定在那一点图像从左到右透明值的属性的钥匙点。

      2. 在数字序列中设置以下时间和值属性:

      • 时间 = 0 , = 0.25
      • 时间 = .101 , = 0.875
      • 时间 = .183 , = 0
      • 时间 = .3 , = 1
      • 时间 = .7 , = 1
      • 时间 = 1 , = 0.9
  5. 从步骤 2 复制 图像标签

  6. 在重复标签中选择 UIGradient 对象,然后在 属性窗口 中,

    1. 旋转 设置为 -45,以使图像几乎相互映射在 Y 轴上。

    2. 修改 透明 以使闪光看起来更有机。

      1. 单击 透明 属性,然后单击 按钮。显示数字序列弹出。
      2. 选择第三个关键帧,然后单击 删除 按钮。
  7. 在示例 激光标签 位置文件中引用以下 脚本,显示程序动态显示力场屏幕,当玩家加入或重新加入一轮时。

以下 ReplicatedStorage.ForceFieldClientVisuals 客户端脚本将默认 ForceField 视觉替换为 StarterGui.ForceFieldGui 。当玩家加载到体验并在 SpawnLocation 上生成一个具有大于 0 的 Duration 属性时,每个体验的默认行为是为每个虚拟形象提供一个防护蓝球,使他们暂时无法失去生命值。

该脚本首先听当 ForceField 被添加到角色时,禁用默认的第一人称力场视觉效果,然后启用 ForceFieldGui ScreenGui 对象。请注意,这不会在玩家看到其他玩家重生回体验时影响第三人称视觉效果。

First-person force field visuals include a futuristic hexagonal grid on the perimeter of the screen.

第一人称力场视觉
>

Third-person force field visuals include a blue sparkling orb around the player spawning into the experience.

第三人称力场视觉效果
>


local Players = game:GetService("Players")
local localPlayer = Players.LocalPlayer
local function onCharacterAddedAsync(character: Model)
local forceField = character:WaitForChild("ForceField", 3)
if not forceField then
-- 如果玩家在禁用力场的生成点生成时
return
end
forceField.Visible = false
localPlayer.PlayerGui:WaitForChild("ForceFieldGui").Enabled = true
forceField.Destroying:Wait()
localPlayer.PlayerGui.ForceFieldGui.Enabled = false
end
if localPlayer.Character then
onCharacterAddedAsync(localPlayer.Character)
end
localPlayer.CharacterAdded:Connect(onCharacterAddedAsync)

重生屏幕

重生屏幕是一个用于降低视窗亮度通知玩家他们已被标记出来,并且服务器正在重生他们回到他们的产卵区的过程中的用户界面元素。这个用户界面元素很重要,因为它给玩家留时间来处理他们被标记出的问题,并在他们重新加入活跃回合之前策划他们的下一步。

有关样品激光标签体验中的自定义重生行为的更多信息,请参阅重生角色从游戏脚本教程中。

要准确重现示例 激光标签 体验中的重生屏幕:

  1. 创建中心信息横幅。

    1. 将 图像标签 插入 OutStateGui 对象。

      1. 探索器 窗口中,导航到 StarterGui 服务。

      2. 将鼠标悬停在其子对象 OutStateGui 上,然后单击 标志。将显示上下文菜单。

      3. 从上下文菜单中插入一个 图像标签

    2. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在自身中间设置新按钮的起始点(标签左右的 50% 和标签顶部到底的 50%)。

      2. 背景透明 设置为1,使标签的背景完全透明。

      3. 位置 设置为 {0.5, 0},{0.5, 0} 以在容器中设置标签(50% 来自父屏幕的左到右,50% 来自父屏幕的顶到底)。

      4. 大小 设置为{0.48, 0},{0.06, 0}以扩展标签(48%横向和6%垂直于父屏幕GUI)

      5. 名称 设置为

      6. 图像 设置为 rbxassetid://14304827265 以使图像成为椭圆形。

      7. 图像颜色 设置为 0,0,0 使椭圆变黑。

      8. 图像透明度 设置为0.3,以减少标签的不透明度 30%,并与体验中的所有黑色用户界面元素匹配。

    3. UIAspectRatioConstraint 插入 以确保标签和其子元素的 UI 比例率无论玩家屏幕大小如何都保持相同。

    4. 选择新约束,然后在 属性窗口 中将 比例率 设置为 13.78

    5. 文本标签 插入 用于信息文本。

    6. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在标签中间设置标签的起始点(标签左侧到右侧的 50%,标签顶部到底部的 50%)。

      2. 背景透明 设置为1,使标签的背景完全透明。

      3. 位置 设置为{0.5, 0},{0.5, 0},将标签设置在其父标签的中间(父标签左右的 50% 和父标签顶部到底的 50%)。

      4. 尺寸 设置为 {.85, 0},{0.55, 0} 以便文本占用大部分椭圆形区域(85% 横向和 55% 垂直于父标签)

      5. 名称 设置为 BodyTextLabel

      6. 字体面 设置为 蒙特塞拉特 以适应未来主义的审美。

      7. 重量 设置为 粗体 以加粗字体。

      8. 文本 设置为 重生… .

      9. TextColor3 设置为 255, 255, 255 使文本变白。

      10. 启用 文本缩放

  2. 创建标题。

    1. 图像标签 插入

    2. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 1 以在标签底部中设置标签的起始点(标签左侧到右侧的 50% 和标签顶部到底的 100%)。

      2. 背景透明 设置为1,使标签的背景完全透明。

      3. 位置 设置为{0.5, 0},{0, 0},将标签设置在其父标签的顶部中间(父标签左侧的 50% 到右侧,父标签顶部的 0%)。

      4. 大小 设置为{0.46, 0},{0.56, 0}以扩展标签(46%横向和56%垂直于父标签)

      5. 名称 设置为 头部

      6. 图像 设置为 rbxassetid://14304826985 以使图像成为多向渐变

      7. 图像颜色 设置为 245, 46, 46 以将渐变红用作标志,表示玩家在回合结束时暂时处于非活跃状态。

    3. 文本标签 插入 标题 对于信息文本。

    4. 选择新标签,然后在 属性 窗口中,

      1. 锚点 设置为 0.5, 0.5 以在标签中间设置标签的起始点(标签左侧到右侧的 50%,标签顶部到底部的 50%)。

      2. 背景透明 设置为1,使标签的背景完全透明。

      3. 位置 设置为{0.5, 0},{0.5, 0},将标签设置在其父标签的中间(父标签左右的 50% 和父标签顶部到底的 50%)。

      4. 尺寸 设置为 {.85, 0},{0.55, 0} 以便文本占用大部分渐变区域(横向 85% 和垂向 55% 的父标签)

      5. 名称 设置为 头部文本标签

      6. 字体面 设置为 蒙特塞拉特 以适应未来主义的审美。

      7. 重量 设置为 黑色 以加粗字体。

      8. 文本 设置为 标记 - 你被淘汰了! 9. 将 TextColor3 设置为 255, 255, 255 使文本变白。

      9. 启用 文本缩放

  3. 创建屏幕边缘的渐变。

    1. 图像标签 插入 OutStateGui
    2. 选择新标签,然后在 属性 窗口中,
      1. 锚点 设置为 0.5, 0.5 以在标签中间设置标签的起始点(标签左侧到右侧的 50%,标签顶部到底部的 50%)。
      2. 背景颜色3 设置为 0,0,0 以将标签的背景颜色设置为黑色。
      3. 背景透明 设置为0.5,使标签的背景半透明。
      4. 位置 设置为 {0.5, 0},{0.5, 0} 以在容器中间设置标签(从左到右父屏幕的 50% 和父屏幕的顶部到底 50%)。
      5. 尺寸 设置为 {1, 0},{1, 0} 以将标签扩展到整个屏幕(父屏幕的横向 100% 和垂直 100%)
      6. ZIndex 设置为 -1 以显示其他 UI 元素背后的渐变。
      7. 名称 设置为 头部
      8. 图像 设置为 rbxassetid://14309518613 以使图像变为渐变边界。
      9. 图像透明度 设置为 0.1 以使渐变略显透明。
  4. 在示例 激光标签 位置文件中引用以下 脚本,当玩家的生命值达到零时显示重生屏幕,他们正在回到自己团队的重生区域。

以下 ReplicatedStorage.PlayerStateHandler 客户端脚本包含启动不同类型行为的功能,根据 playerState 属性。所有事件响应在此脚本中逻辑组合在一起,因为它们需要启用或禁用玩家控制、相机移动和哪个 UI 层可见的相似行为。

当玩家的生命值达到零时,其 playerState 变为 TaggedOut ,这会触发 onTaggedOut() 函数。onTaggedOut() 立即触发以下行为:

  • 玩家无法在竞技场移动。
  • 玩家无法移动相镜头。
  • 玩家无法使用他们的爆破器。
  • StarterGui.OutStateGui 变为专用启用。

当玩家重生时,其playerState变为SelectingBlaster,这会触发onSelectingBlaster()函数。onSelectingBlaster() 然后仅启用 StarterGui.PickABlasterGui,这会自动禁用重生屏幕。了解有关这些条件的更多信息,请参阅处理客户端状态从游戏脚本教程中。


local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local PlayerState = require(ReplicatedStorage.PlayerState)
local PlayerAttribute = require(ReplicatedStorage.PlayerAttribute)
local BlasterState = require(ReplicatedStorage.Blaster.BlasterState)
local togglePlayerMovement = require(script.togglePlayerMovement)
local togglePlayerCamera = require(script.togglePlayerCamera)
local scheduleDestroyForceField = require(ReplicatedStorage.scheduleDestroyForceField)
local localPlayer = Players.LocalPlayer
local playerGui = localPlayer.PlayerGui
local guiLayers = {
playerGui:WaitForChild("HUDGui"),
playerGui:WaitForChild("OutStateGui"),
playerGui:WaitForChild("PickABlasterGui"),
}
-- 禁用所有界面层,除了指定的例外
local function setGuiExclusivelyEnabled(enabledGui: ScreenGui?)
-- 图形用户界面层包含一个列表,列出应仅设置的图形用户界面。
for _, screenGui in guiLayers do
screenGui.Enabled = screenGui == enabledGui
end
end
local function onSelectingBlaster()
-- 启用相机,让玩家在选择爆破器时可以四处看看
togglePlayerCamera(true)
togglePlayerMovement(false)
setGuiExclusivelyEnabled(playerGui.PickABlasterGui)
-- 在选择爆破器时禁用爆破器
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onPlaying()
-- 在选择爆破器后启用玩家移动
togglePlayerMovement(true)
setGuiExclusivelyEnabled(playerGui.HUDGui)
-- 在游戏时启用爆破器
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Ready)
-- 当玩家开始游戏时,安排摧毁力场逻辑
scheduleDestroyForceField()
end
local function onTaggedOut()
-- 在标记时禁用控件
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- 在标记时禁用爆破器
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onInLobby()
-- 在大厅中启用控件
togglePlayerMovement(true)
togglePlayerCamera(true)
-- 在大厅中隐藏所有 HUD
setGuiExclusivelyEnabled(nil)
-- 在大厅中禁用爆破器
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onPlayerStateChanged(newPlayerState: string)
if newPlayerState == PlayerState.SelectingBlaster then
onSelectingBlaster()
elseif newPlayerState == PlayerState.Playing then
onPlaying()
elseif newPlayerState == PlayerState.TaggedOut then
onTaggedOut()
elseif newPlayerState == PlayerState.InLobby then
onInLobby()
else
warn(`Invalid player state ({newPlayerState})`)
end
end
-- 如果设置,处理初始玩家状态
local initialPlayerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
onPlayerStateChanged(initialPlayerState)
local function updateFromPlayerState()
onPlayerStateChanged(localPlayer:GetAttribute(PlayerAttribute.playerState))
end
-- 处理未来玩家状态更新
localPlayer:GetAttributeChangedSignal(PlayerAttribute.playerState):Connect(updateFromPlayerState)
-- 确保在重生后仍然应用更改
localPlayer.CharacterAdded:Connect(updateFromPlayerState)

创建表面图形用户界面对象

要在 3D 空间中显示用于 每个单独玩家 的脚本逻辑的部件表面上的用户界面,您可以将 SurfaceGui 对象父级到您想在 ReplicatedStorage 服务中显示用户界面的部件。这种技术可确保您的用户界面和其脚本逻辑对服务器和每个玩家的客户端都可用。

SurfaceGui 对象包含所有显示在零件表面的 3D 空间上的 GuiObjects 。示例激光标签体验只包含一个 SurfaceGui 对象的实例:显示在每个玩家的发射器上的冷却计时器。这个对象需要为每个玩家编写脚本逻辑,因为它积极回应每个玩家的输入,并提供视觉反馈,当他们可以再次发射爆破器时。

要创建一个 SurfaceGui 对象:

  1. 资源管理器 窗口中,将鼠标悬停在 ReplicatedStorage 服务上,然后单击 标志。将显示上下文菜单。

  2. 从上下文菜单中插入一个 零件 对象。

  3. ScreenGui 对象插入零件。

  4. 根据其子 UI 元素的上下文重命名 表面图形用户界面

  5. 重复此过程以显示在零件表空间上的每个用户界面元素。

冷却计

冷却计是一个用于向玩家通知他们在爆炸冲击波前需要等待多久的 UI 组件。这短暂的暂停使玩家无法像点击或按下按钮那样快速爆炸,这对激光标签游戏来说是不现实的

要准确重现样本 激光标签 体验中的冷却计时器:

  1. 创建一个部件来支持你的 SurfaceGui 对象。

    1. 探索器 窗口中,将鼠标悬停在 工作区 上,然后单击 ⊕ 标志。显示上下文菜单。
    2. 从上下文菜单中插入 部分。这是零件的临时位置,可以让您在每个过程步骤的更改中可视化。
  2. 位置和向部件周围的位置放置玩家角色的爆破器,然后在 属性 窗口中,

    1. 透明 设置为 1 以使零件完全透明。

    2. 名称 设置为 CooldownBarPrefab

    3. 大小 设置为0.169, 0.027, 2.537,将零件缩放到与冲击波长度相近的尺寸。

    4. 禁用 可碰撞可查询

  3. 表面图形用户界面 插入 冷却条模板

  4. 选择新的 表面图形用户界面 ,然后在 属性窗口 中,

    1. 设置为 顶部 ,以便 UI 显示面向上方。

    2. 光影响最大距离 设置为 0

    3. 像素每学分 设置为 200

  5. 创建黑色条。

    1. 图像标签 插入 表面图形用户界面

    2. 选择新标签,然后在 属性 窗口中,

      1. 移除默认 图像 值。
      2. 锚点 设置为 0.5, 0.5 以在标签中间设置标签的起始点(标签左侧到右侧的 50%,标签顶部到底部的 50%)。
      3. 背景颜色3 设置为 0,0,0 以将标签的背景颜色设置为黑色。
      4. 背景透明 设置为0.4,使标签的背景半透明。
      5. 位置 设置为 {0.5, 0},{0.5, 0} 以在容器中设置标签(从左到右的父 SurfaceGui 的 50%,从顶到底的父 SurfaceGui 的 50%)。
      6. 尺寸 设置为 {1, 0},{1, 0} 以将标签扩展到整个部分(100% 横向和 100% 垂直于父 SurfaceGui)
      7. 名称 设置为 容器
  6. 圆化容器的角。

    1. UICorner 对象插入 容器

    2. 选择 UICorner ,然后在 属性 窗口中将 角度半径 设置为0.15, 0以稍微弯圆角。

  7. 创建红色栏。

    1. 图像标签 插入 容器
    2. 选择新标签,然后在 属性 窗口中,
      1. 移除默认 图像 值。
      2. 锚点 设置为 1, 0.5 以在标签右中设置标签的起始点(标签左到右的 100%,标签顶到底的 50%)。
      3. 背景颜色3 设置为 172, 13, 13 将标签的背景颜色设置为深红色
      4. 背景透明 设置为0.2,使标签的背景略透明。
      5. 名称 设置为
      6. 位置 设置为{1, 0},{0.5, 0}将标签设置在容器右中间(从左到右的父标签的 100%,从顶到底的父标签的 50%)。
      7. 大小 设置为{0, 0},{1, 0},将标签延长到父标签顶部(0%横向和100%垂直的父标签)。这一步也有助于在步骤 8 中发生的渐变行为。
  8. 圆化标签的角落。

    1. UICorner 对象插入
    2. 选择 UICorner ,然后在 属性 窗口中将 角度半径 设置为0.15, 0以稍微弯圆角。
  9. 冷却条模板 移至 复制存储

    1. 创建一个文件夹结构来组织您的 UI 对象。样例使用了一个子文件夹 Instances 和一个孩子文件夹 Guis 的文件夹。

    2. 冷却条模板 移至 图形用户界面

  10. 在示例 激光标签 位置文件中引用以下 脚本,程序atically将冷却计附加到玩家的爆破器上,然后在玩家爆破他们的爆破器后动画红色条。

以下 ReplicatedStorage.FirstPersonBlasterVisuals 客户端脚本处理玩家的第一人称爆破器的所有视觉逻辑。它需要一组模块脚本,共同设置激光标签游戏中感觉更具现实性的爆破视觉效果,包括 FirstPersonBlasterVisuals.addCooldownBarFirstPersonBlasterVisuals.runCooldownBarEffect


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")
local BlastData = require(ReplicatedStorage.Blaster.BlastData)
local PlayerAttribute = require(ReplicatedStorage.PlayerAttribute)
local PlayerState = require(ReplicatedStorage.PlayerState)
local getBlasterConfig = require(ReplicatedStorage.Blaster.getBlasterConfig)
local runBlastVisuals = require(script.runBlastVisuals)
local setupAnimations = require(script.setupAnimations)
local addCooldownBar = require(script.addCooldownBar)
local runCooldownBarEffect = require(script.runCooldownBarEffect)
local laserBlastedBindableEvent = ReplicatedStorage.Instances.LaserBlastedBindableEvent
local RIG_OFFSET_FROM_CAMERA = CFrame.new(2, -2, -3) * CFrame.Angles(math.rad(0.25), math.rad(95.25), 0)
local localPlayer = Players.LocalPlayer
local currentCamera = Workspace.CurrentCamera
local rigModel = nil
local cooldownBar = nil
local animations = {}
local function addFirstPersonVisuals()
local blasterConfig = getBlasterConfig()
-- 添加第一个人物骨架
rigModel = blasterConfig.RigModel:Clone()
rigModel.Parent = Workspace
-- 添加冷却条
cooldownBar = addCooldownBar(rigModel.PrimaryPart.CooldownBarAttachment)
animations = setupAnimations(blasterConfig, rigModel)
end
local function removeFirstPersonVisuals()
for _, animation in animations do
animation:Stop()
animation:Destroy()
animation = nil
end
if rigModel then
-- 这也会摧毁冷却条,因为它属于骨架
rigModel:Destroy()
rigModel = nil
end
end
-- 在爆炸发生时运行第一人称视觉效果
laserBlastedBindableEvent.Event:Connect(function(blastData: BlastData.Type)
runBlastVisuals(rigModel.PrimaryPart.TipAttachment, blastData, animations.blastAnimation)
runCooldownBarEffect(cooldownBar)
end)
-- 如果存在,将装备绑定到相机
RunService.RenderStepped:Connect(function()
if rigModel then
-- 更新到相镜头位置和 RIG_OFFSET_FROM_CAMERA 对应的装备的 CFrame
rigModel:PivotTo(currentCamera.CFrame * RIG_OFFSET_FROM_CAMERA)
end
end)
-- 在爆破器类型更改时更改视觉效果的处理方式
localPlayer:GetAttributeChangedSignal(PlayerAttribute.blasterType):Connect(function()
local playerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
if playerState == PlayerState.Playing then
removeFirstPersonVisuals()
addFirstPersonVisuals()
end
end)
-- 当玩家状态更改时,处理更改的视觉效果
localPlayer:GetAttributeChangedSignal(PlayerAttribute.playerState):Connect(function()
local newPlayerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
-- 当玩家选择爆破器或进入大厅时,移除视觉效果
if newPlayerState == PlayerState.SelectingBlaster or newPlayerState == PlayerState.InLobby then
removeFirstPersonVisuals()
-- 当玩家完成选择爆破器后,添加视觉效果。
elseif newPlayerState == PlayerState.Playing then
addFirstPersonVisuals()
end
end)

创建广告牌对象

为了在 3D 空间中显示响应脚本逻辑且始终面向每个玩家的相机的 UI 元素,例如玩家名称或地图标记,您可以创建一个 BillboardGui 对象作为 3D 空间中存在的 BasePartAttachment 的子对象。

示例激光标签体验包括两个独立的 BillboardGui 对象在 ReplicatedStorage 服务中:

  • 其他玩家指示器图形预制 - 在玩家在回合中活跃时,在他们的头顶显示粉色或绿色圆圈。
  • 标记退出指示器模板 - 在他们退出回合时显示在玩家头顶上。

在创建一个 BillboardGui 对象之后,您可以根据每个容器的目的创建并自定义其子 GuiObjects 对象。要展示,在即将关注随的直接部分中,您将学习如何在样品激光标签体验中实现指示器类型的用户界面元素。 你可以调整过程的任何部分来满足自己的体验规格

要创建一个 BillboardGui 对象:

  1. 浏览器 窗口中,将鼠标悬停在 BasePartAttachment 上,然后单击 标志。将显示上下文菜单。
  2. 从上下文菜单中插入一个 BillboardGui 对象。
  3. 根据其子 UI 元素的上下文重命名 BillboardGui
  4. 重复这个过程以显示每个需要在玩家头顶上下文显示的 UI 元素。

团队指示器

团队指示器是一个用于通知玩家哪个团队其他玩家在回合中属于的 UI 元素,以便他们轻松区分自己的盟友和敌方团队成员。这些信息很重要,因为第一人称射击体验的游戏玩法需要玩家在战斗区域内做出快速的战略决定,以免被标记并失去比匹配。

要准确重现样本 激光标签 体验中的团队指示器:

  1. 广告牌Gui 对象插入到临时骨架中。

    1. 从工具栏的 虚拟形象 选项卡,单击 装备建造器

    2. 从可用选项中选择。样本使用了一个 R15 装备输入、一个 女性 身体形状和一个 Rthro 虚拟形象。该装备在 3D 视窗和 探索器 窗口下以名称 装备 显示两者都。

    3. 探索器 窗口中,导航到装备的子网格 头部 网格,然后单击 标志。显示上下文菜单。

    4. 从上下文菜单中插入 BillboardGui

  2. 选择新的 BillboardGui ,然后在 属性窗口 中,

    1. 光影响 设置为 0 以防环境光影响指示器的颜色。

    2. 名称 设置为 OtherPlayerIndicatorPrefab

    3. 大小 设置为{0, 10},{0, 10}以使标签显著变小。

    4. 螺柱偏移世界空间 设置为 0, 4, 0 以将其放置在机骨架的头部上。

  3. 框架 对象插入 OtherPlayerIndicatorPrefab

  4. 选择新框架,然后在 属性 窗口中,

    1. 锚点 设置为 0.5, 0.5 以在框架中间设置框架的起始点(标签左右的 50% 和标签顶部到底的 50%)。

    2. 背景颜色3 设置为 255, 3, 0 将框架的背景颜色设置为红色作为占位符颜色。

    3. 位置 设置为 {0.5, 0},{0.5, 0} 以将框架设置为容器的中间(从左到右的父广告图标的 50%,从上到下的父广告图标的 50%)。

    4. 尺寸 设置为 {1, -2},{1, -2} 以缩短框架到广告牌的表面积。

  5. UICorner 对象插入 框架 以完全圆化角落。

  6. UIStroke 对象插入 框架 以概述指示器的圆圈。

  7. 其他玩家指示器预制件 移至 复制存储

  8. 在示例 Laser Tag 1A 位置文件中引用以下脚本,除非它们属于敌方团队并被遮蔽,否则每个激活回合的每个玩家都会显示团队指示器

当玩家生成到竞技场时,下面的 ReplicatedStorage.OtherPlayerIndicatorGuiSetup 脚本运行,进行激活回合。它通过调用 addIndicatorToCharacter() 函数附加团队指示器,该函数找到每个参加回合的玩家角色的 Head 对象。如果他们还没有团队指示器,那么脚本将克隆并添加 其他玩家指示器预制 UI 到角色的 Head 中,然后将团队指示器颜色设置为他们的团队颜色。

如果其他玩家属于同一队伍,团队指示器始终显示,即使他们躲在 3D 空间中的物体后;如果其他玩家属于敌队,团队指示器只会显示,如果 3D 空间中没有物体遮蔽他们。


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local localPlayer = Players.LocalPlayer
local otherPlayerIndicatorPrefab = ReplicatedStorage.Instances.Guis.OtherPlayerIndicatorPrefab
local characterSpawnConnectionsByPlayer: { [Player]: RBXScriptConnection } = {}
local playerAddedConnection: RBXScriptConnection?
local function removeIndicatorFromPlayer(player: Player)
if not player.Character then
return
end
local head = player.Character:WaitForChild("Head", 3)
if not head then
return
end
local gui = head:FindFirstChild(otherPlayerIndicatorPrefab.Name)
if gui then
gui:Destroy()
end
end
local function addIndicatorToCharacter(otherCharacter: Model?)
local otherPlayer = Players:GetPlayerFromCharacter(otherCharacter)
if not otherPlayer then
return
end
task.spawn(function()
local otherHead = otherCharacter:WaitForChild("Head", 3)
if not otherHead then
return
end
-- 仅向参加回合的玩家添加指标
if not otherPlayer.Team then
return
end
-- 避免添加重复指标,只有如果它不存在才创建一个新的指标
local gui = otherHead:FindFirstChild(otherPlayerIndicatorPrefab.Name)
if not gui then
gui = otherPlayerIndicatorPrefab:Clone()
gui.Frame.BackgroundColor3 = otherPlayer.TeamColor.Color
gui.Parent = otherHead
end
-- 只有当玩家友好时,指示器才会始终处于顶部
local isFriendly = otherPlayer.Team == localPlayer.Team
gui.AlwaysOnTop = isFriendly
end)
end
local function addIndicatorWhenCharacterSpawns(player: Player)
if characterSpawnConnectionsByPlayer[player] then
return
end
local connection = player.CharacterAdded:Connect(addIndicatorToCharacter)
characterSpawnConnectionsByPlayer[player] = connection
end
local function stopSyncingIndicators()
for _, connection in characterSpawnConnectionsByPlayer do
connection:Disconnect()
end
table.clear(characterSpawnConnectionsByPlayer)
if playerAddedConnection then
playerAddedConnection:Disconnect()
playerAddedConnection = nil
end
for _, player in Players:GetPlayers() do
removeIndicatorFromPlayer(player)
end
end
local function addIndicatorToPlayer(player: Player)
if player == localPlayer then
return
end
addIndicatorToCharacter(player.Character)
addIndicatorWhenCharacterSpawns(player)
end
local function startSyncingIndicators()
for _, player in Players:GetPlayers() do
addIndicatorToPlayer(player)
end
if not playerAddedConnection then
playerAddedConnection = Players.PlayerAdded:Connect(addIndicatorToPlayer)
end
end
local function onLocalTeamChanged()
local localTeam = localPlayer.Team
if localTeam then
startSyncingIndicators()
else
stopSyncingIndicators()
end
end
localPlayer:GetPropertyChangedSignal("Team"):Connect(onLocalTeamChanged)
onLocalTeamChanged()

标记出指示器

标记的退出指示器是一个用于通知玩家其他玩家已不再活跃在回合中,正在返回到他们的生成区的 UI 元素。这些信息很重要,因为第一人称射击体验的游戏玩法需要玩家尽快移动到下一个目标,以免在同一地点长时间游戏而导致他们在竞技场上变得脆弱。

要准确重现标记的指示器在样例 激光标签 体验中:

  1. 广告图形用户界面 对象插入到临时装备中,以便您可以在每个过程步骤的更改中进行视觉化。

    1. 从工具栏的 虚拟形象 选项卡,单击 装备建造器

    2. ​从可用选项中选择。样本使用了一个 R15 装备输入、一个 男性 身体形状和一个 Rthro 虚拟形象。该装备在 3D 视窗和 探索器 窗口下以名称 装备 显示两者都。

    3. 探索器 窗口中,导航到装备的子网格 头部 网格,然后单击 标志。显示上下文菜单。

    4. 从上下文菜单中插入 BillboardGui

  2. 选择新的 BillboardGui ,然后在 属性窗口 中,

    1. 光影响 设置为 0 以防环境光影响指示器的颜色。

    2. 名称 设置为 TaggedOutIndicatorGuiPrefab

    3. 大小 设置为{3, 0},{0.5, 0}以扩展标签的空间。

    4. 距离设置 设置为 0, 3.25, 0 以将其放置在玩家的头顶上。

  3. 图像标签 对象插入 标记出指示器模板预制 .

  4. 选择新标签,然后在 属性 窗口中,

    1. 锚点 设置为 0.5, 0.5 以在标签中间设置标签的起始点(标签左侧到右侧的 50%,标签顶部到底部的 50%)。
    2. 背景透明 设置为1,使标签的背景完全透明。
    3. 名称 设置为 框架
    4. 位置 设置为 {0.5, 0},{0.5, 0} 以将标签设置为容器的中间(从左到右的父广告图标的 50%,从顶到底的父广告图标的 50%)。
    5. 尺寸 设置为 {1, 0},{1, 0} 以将标签扩展到整个广告牌GUI(100%横向和100%垂直于父广告牌GUI)。
    6. 图像 设置为 rbxassetid://14304826985 以使图像成为多向渐变
    7. 图像颜色 设置为 245, 46, 46 以涂红标签。
  5. 文本标签 对象插入 框架 .

  6. 选择新标签,然后在 属性 窗口中,

    1. 锚点 设置为 0.5, 0.5 以在标签中间设置标签的起始点(标签左侧到右侧的 50%,标签顶部到底部的 50%)。

    2. 背景透明 设置为1,使标签的背景完全透明。

    3. 名称 设置为 BodyTextLabel

    4. 位置 设置为{0.5, 0},{0.5, 0}将标签设置为容器的中间(从左到右的父标签的50%和父标签的顶部到底的50%)。

    5. 尺寸 设置为 {0.85, 0},{0.7, 0} 以便文本占用大部分渐变区域(85% 横向和 70% 垂直于父图像标签)

    6. 字体面 设置为 蒙特塞拉特 以适应未来主义的审美。

    7. 重量 设置为 粗体 以加粗字体。

    8. 文本 设置为 标记

    9. TextColor3 设置为 255, 255, 255 使文本变白。

    10. 启用 文本缩放

  7. 标签出指示器模板 移至 复制存储

  8. 在示例 激光标签 1A 放置文件中引用以下 ServerScriptService 脚本,在玩家重生到他们团队的生成区时显示标记的指示器。

以下 ServerScriptService.SetupHumanoid 服务器脚本在玩家加载体验时立即运行。它确保每当玩家的角色添加到数据模型时,setupHumanoidAsync 都会调用他们的Humanoid


local Players = game:GetService("Players")
local setupHumanoidAsync = require(script.setupHumanoidAsync)
local function onCharacterAdded(player: Player, character: Model)
local humanoid = character:WaitForChild("Humanoid")
setupHumanoidAsync(player, humanoid)
end
local function onPlayerAdded(player: Player)
-- 如果玩家已经有角色,请调用 onCharacterAdded
if player.Character then
onCharacterAdded(player, player.Character)
end
-- 为此玩家的所有未来角色生成呼叫 onCharacterAdded
player.CharacterAdded:Connect(function(character: Model)
onCharacterAdded(player, character)
end)
end
-- 为已经在游戏中的任何玩家调用 onPlayerAdded
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end
-- 为所有未来的玩家调用 onPlayerAdded
Players.PlayerAdded:Connect(onPlayerAdded)

恭喜您完成用户界面设计课程!现在您已经有经验创建艺术风格、设计布局并在 Studio 中从头到尾实现设计,您可以通过新的用户界面和功能扩展项目,或按照额外的教程课程,例如 游戏脚本课程 ,教您关于样本激光标签体验的一般组织和关键实施细节。创作愉快!