创建团队 让您可以将玩家分成多个组,以争夺完成共同目标,例如获得最多分数或在其他敌对团队成员之前穿越终点线。在第一人称射击游戏中,创建团队尤其重要,因为它为玩家建立了复杂的、协调的游戏策略,超出了任何单一玩家的技能范围。
以 示例激光标记体验 为参考,本节教程教您如何将玩家分成团队,包括脚本指导:
- 使用 Teams 服务的默认功能将玩家分配到绿色或粉色团队中。
- 通过屏幕和体验内的团队指示器帮助玩家区分他们的盟友和敌方团队成员。
- 启用宽容的游戏玩法,不会因击倒队友而惩罚玩家。
完成本节后,您将了解允许玩家生成或重生到中立大厅或团队生成区的脚本,自定义第一人称力场视觉效果,并处理来自服务器和客户端的客户端状态。

分配团队颜色
示例激光标记体验使用 Teams 服务作为创建两个团队的基础,因为该服务提供内置的团队排序行为,可以开箱即用。例如,在没有任何额外脚本工作的情况下,该服务处理以下操作:
- 将玩家均匀地排序和平衡到每个团队。
- 在排行榜上将玩家归类到他们的团队下。
- 将玩家名称在三维空间中染色为其对应的团队颜色。
- 将玩家生成到只有他们的团队可以访问的不同生成位置。
由于这种默认功能,示例启用了 Teams 服务,然后使用两个不同的 Team 对象,并赋予不同的 Team.Color 属性值以表示每个团队:薄荷色表示在地图一侧汇聚的团队,肉色表示在地图另一侧汇聚的团队。这些具体的颜色非常有用,因为它们是互补的,意味着它们彼此对比良好,并使玩家能够轻松扫描周围环境,并在建筑物和其他玩家之间定向。




注意 Team.Color 属性的确切 BrickColor 名称非常重要,因为体验在多个脚本中使用该名称来跟踪玩家如何分组到团队中,在玩家在回合中击倒敌方玩家时递增积分,并更新自定义 UI 元素。例如,当回合开始时,ReplicatedStorage ⟩ HUDGuiSetup 需要 startSyncingTeamColor 和 startSyncingTeamPoints,两者都引用 Team.Color 以对每个团队执行独特的操作。
startSyncingTeamColor 引用 Team.Color 以便为玩家在其屏幕左下角的团队指示器分配正确的颜色和图标。


local function setPlayerTeamIcon(gui: ScreenGui)
for _, teamColorIcon in gui.PlayerDisplay.TeamIcons:GetChildren() do
local iconTeamColor = teamColorIcon:GetAttribute(GuiAttribute.teamColor)
teamColorIcon.Visible = localPlayer.TeamColor == iconTeamColor
end
end
local function startSyncingTeamColor(gui: ScreenGui)
setPlayerTeamIcon(gui)
localPlayer:GetPropertyChangedSignal("Team"):Connect(function()
setPlayerTeamIcon(gui)
end)
end
显示团队指示器
一旦玩家被分配到一个团队,他们需要能够快速识别他们所属的团队,并区分他们的盟友和敌方团队成员。这种能力很重要,因为第一人称射击体验的游戏玩法要求玩家在战区做出快速的战略决定,以免被击倒和失去回合。
为了使玩家成功,示例激光标记体验提供了多种屏幕和 3D 空间内的团队指示器:
- 玩家指示器 – 自定义屏幕 UI,显示玩家的团队颜色和图标。
- 团队指示器 – 自定义体验内 UI,显示玩家的团队颜色。
- 排行榜指示器 – 默认 Teams 服务的屏幕 UI,将玩家分组到他们的团队颜色下。
- 名称染色 – 默认 Teams 服务的体验内 UI,将玩家的名称上方染色为其团队颜色。




除了从教程的上一部分分配团队颜色外,您不需要为排行榜指示器或名称染色做任何额外的工作,但自定义 UI 团队指示器需要更多的编程工作,以便在敌方指示器被墙壁遮挡时显示指示器并遮挡敌方指示器。有关控制自定义 UI 行为的脚本的完整说明,以及如何实现每个 UI 元素本身,请参见 UI 课程中的 玩家指示器 和 团队指示器。
禁用误伤
虽然一些第一人称射击体验会惩罚击倒自己队友的玩家,但示例激光标记体验通过禁用误伤来允许更宽容的游戏玩法。这个设计决定使每个人都只能增加他们的团队得分,而不会因游戏事故而减少得分。
要了解示例如何实现此功能,请查看 ServerScriptService ⟩ LaserBlastHandler ⟩ processTaggedPlayers ⟩ onPlayerTagged 如何处理对被击倒玩家的伤害。当服务器检测到玩家的爆炸和另一名玩家之间的碰撞时,它会调用 onPlayerTagged 函数,以了解哪个玩家发射了爆炸、哪个玩家被击中以及应该从玩家的健康中移除多少伤害,这取决于爆炸器的类型。
local function onPlayerTagged(playerBlasted: Player, playerTagged: Player, damageAmount: number)
在减少健康之前,脚本首先检查被击中玩家是否与发射爆炸的玩家在同一个团队。如果他们在同一个团队,脚本将完全忽略这个爆炸数据。
local character = playerTagged.Characterlocal isFriendly = playerBlasted.Team == playerTagged.Team-- 禁止误伤if isFriendly thenreturnend
但是,如果被击中的玩家 是在 敌方团队,玩家将根据爆炸器类型承受相应的伤害。此外,如果玩家受到足够的伤害被击倒,脚本将为发射爆炸的玩家的团队奖励一个积分。有关示例如何跟踪积分的更多信息,请参见本教程后面的 添加回合。
local humanoid = character and character:FindFirstChild("Humanoid")if humanoid and humanoid.Health > 0 thenlocal damage = math.min(damageAmount, humanoid.Health)humanoid:TakeDamage(damage)if humanoid.Health <= 0 thenScoring.incrementScore(playerBlasted, 1)endendendreturn onPlayerTagged
如果您现在测试体验,所有玩家将随机在竞技场两端的任何生成区生成,而不论他们属于哪个团队,这意味着每个团队将紧挨着生成。
为了解决这个问题,本教程的下一部分教您关于限制团队生成到某些生成位置的自定义逻辑,处理玩家在选择他们的爆炸器后离开生成区时的客户端状态,以及当他们的健康值降到零时将玩家重生回其生成区或大厅区域。