Implementando seus designs é o processo de criar seus wireframes no Studio usando elementos de UI integrados e personalizados com scripts que acionam sua UI de forma contextual. Esta etapa emocionante do tutorial é onde você pode ver todos os seus designs e o duro trabalho se juntarem em um conjunto coeso de fluxos de trabalho que estão completos e prontos para interação dos jogadores.
Usando o experiência de laser tag de amostra .rbxl como referência, esta seção do currículo de design de interface do usuário mostra como dar vida ao seu planejamento de UI, incluindo orientações sobre:
- Recuperar IDs de ativos da biblioteca de ativos de UI para que você possa recriar os componentes de UI da experiência de laser tag de amostra.
- Emular vários dispositivos diretamente no Studio para ver como sua UI é exibida em diferentes telas e proporções de aspecto.
- Criar objetos ScreenGui, SurfaceGui e BillboardGui para exibir sua UI nas telas dos jogadores, superfícies de partes e dentro do espaço 3D, respectivamente.
Depois de revisar as técnicas nesta seção, você pode aplicá-las aos seus próprios projetos para criar componentes de UI empolgantes que ajudam os jogadores a navegar no que podem fazer dentro de suas experiências.
Obter biblioteca de ativos
As bibliotecas de ativos são coleções de ativos que você pode adicionar ao seu inventário para fácil acesso e reutilização. A biblioteca de ativos que você usará para seu projeto da Creator Store inclui nove ativos individuais de elementos de UI 2D, e as versões finais do componente de objetivo, seletor de blaster e informações do jogador que você está criando nesta seção do tutorial.

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
Para obter a biblioteca de ativos do seu inventário para a sua experiência:
Adicione a biblioteca de ativos ao seu inventário.
- Navegue até a página de detalhes da biblioteca de ativos na Creator Store.
- No canto superior direito, clique no botão Obter Modelo. A biblioteca de ativos agora está no seu inventário, e você pode reutilizar esses ativos em qualquer projeto na plataforma.
No Studio, navegue até a aba Início, então clique no botão Caixa de Ferramentas. A janela Caixa de Ferramentas abre.

Na janela Caixa de Ferramentas, clique na aba Inventário. A classificação Meus Modelos é exibida.

Clique no menu suspenso e selecione a classificação Meus Pacotes.
Clique no tile Componentes de UI da Tela Final, então na janela Explorador, selecione Componentes Concluídos, e arraste-os para o serviço StarterGui. Você pode agora habilitar qualquer um dos componentes finais para referenciar seu design.
Emular dispositivos
O Emulador de Dispositivo do Studio permite que você teste como os jogadores verão e interagirão com sua UI em vários dispositivos. Esta ferramenta é uma parte vital do processo de implementação, pois a proporção de aspecto do seu viewport no Studio não reflete necessariamente a proporção de aspecto das telas que os jogadores usam para acessar sua experiência, e é importante que sua UI seja legível e acessível em todos os dispositivos.
Por exemplo, se você não testar sua UI em uma variedade de tamanhos de tela, jogadores com telas grandes podem não conseguir ler seu texto ou decifrar seus ícones, e jogadores com telas pequenas podem não conseguir ver o espaço 3D porque seus elementos de UI ocupam muito espaço na exibição.
Para emular sua UI em vários tamanhos de tela:
No menu Teste do Studio, ative o Emulador de Dispositivo.
No menu suspenso de resolução, selecione Resolução Real. Isso permite que você veja a verdadeira resolução dos seus elementos de UI no dispositivo que você está emulando.

No menu suspenso de dispositivos, selecione pelo menos um dispositivo nas seções Telefone, Tablet, Desktop e Console.

Criar objetos ScreenGui
Para exibir elementos de UI na tela de cada jogador, você pode criar um objeto ScreenGui no serviço StarterGui. Os objetos ScreenGui são os contêineres principais para a UI na tela, e o serviço StarterGui copia seu conteúdo para o contêiner PlayerGui de cada jogador à medida que eles entram em uma experiência.
Você pode criar vários objetos ScreenGui para organizar e exibir agrupamentos de elementos de UI de forma contextual durante o jogo. Por exemplo, a experiência de laser tag de amostra inclui cinco objetos ScreenGui separados que estão inicialmente desativados até que os jogadores atendam a diferentes condições durante o fluxo principal de usuário da experiência:
- HUDGui - Exibe informações chave sobre a jogabilidade da experiência quando os jogadores estão ativos em uma rodada, como o objetivo e o total de pontos de cada time.
- PickABlasterGui - Exibe todas as opções de blaster quando os jogadores iniciam ou reentram em uma rodada.
- ForceFieldGui - Exibe uma grade hexagonal quando os jogadores estão selecionando um blaster e enquanto eles estão temporariamente invencíveis.
- OutStateGui - Exibe uma borda escura ao redor da tela quando os jogadores são eliminados.
- RoundResultsGui - Exibe uma sobreposição escura sobre a tela com informações sobre qual time ganhou a rodada.
Depois de criar um objeto ScreenGui, você pode criar e personalizar seus filhos GuiObjects de acordo com o propósito de cada contêiner. Para demonstrar, nas seções imediatas que se seguem, você aprenderá como implementar elementos de UI para as três categorias de informações que os jogadores precisam saber para ter sucesso na experiência de laser tag de amostra. Você pode ajustar qualquer parte do processo para atender às especificações de sua própria experiência.
Para criar um objeto ScreenGui:
Na janela Explorador, passe o mouse sobre o serviço StarterGui, e clique no ícone ⊕. Um menu contextual é exibido.
Insira um ScreenGui.

Renomeie o ScreenGui de acordo com o contexto de seus elementos de UI filhos.
Repita este processo para cada agrupamento de elementos de UI que você precisa exibir na tela de cada jogador.

UI do Objetivo
Seguindo as melhores práticas de hierarquia visual do Wireframe Your Layouts, esta seção ensina como implementar todos os elementos de UI na tela relacionados ao objetivo da experiência. Este agrupamento de elementos de UI fica próximo ao topo da tela porque o objetivo e os pontos de cada time têm a maior significância em como ganhar o jogo.

Por exemplo, a amostra fornece um componente de UI de objetivo que os jogadores consultam para saber o que precisam fazer para serem bem-sucedidos em uma rodada. À medida que os jogadores eliminam membros da equipe adversária e ganham pontos, este componente mantém o controle da pontuação de cada equipe em relação ao objetivo geral dentro do prompt do cabeçalho. Para uma revisão de alto nível de todos os scripts do cliente e do servidor que trabalham juntos para acompanhar os pontos, consulte Track points no Currículo de Scripting de Jogabilidade.

Para recriar exatamente a UI do objetivo na amostra Laser Tag:
Crie um contêiner para todo o componente.
Insira um Frame no objeto HUDGui ScreenGui.
- Na janela Explorador, navegue até o serviço StarterGui.
- Passe o mouse sobre seu objeto filho HUDGui, e clique no ícone ⊕. Um menu contextual é exibido.
- No menu contextual, insira um Frame.

Selecione o novo Frame, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 0 para definir o ponto de origem do frame na parte superior do meio (50% da esquerda para a direita do frame, e 0% de cima para baixo do frame).
- Defina BackgroundTransparency para 1 para tornar o fundo do frame completamente transparente.
- Defina Position para {0.5, 0},{0.03, 0} para posicionar o frame próximo ao topo do meio da tela (50% da esquerda para a direita da tela, e 3% de cima para baixo da tela para que haja um pequeno espaço).
- Defina Size para {0.5, 0},{0.13, 0} para que os elementos do frame ocupem uma grande parte do topo da tela para chamar a atenção dos jogadores (50% horizontalmente e 13% verticalmente).
- Defina Name para Objective.

(Opcional) Insira um UIAspectRatioConstraint no Objective para garantir que a proporção do rótulo permaneça a mesma, independentemente do tamanho da tela do jogador. A amostra define sua propriedade UIAspectRatioConstraint.AspectRatio para 7.
Crie um contêiner para os objetos de prompt do objetivo.
Insira um Frame no Objective.
Selecione o novo Frame, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 0 para definir o ponto de origem do frame na parte superior do meio (50% da esquerda para a direita do frame, e 0% de cima para baixo do frame).
- Defina BackgroundTransparency para 1 para tornar o fundo do frame completamente transparente.
- Defina Position para {0.5, 0},{0, 0} para posicionar o frame no meio do contêiner (50% da esquerda para a direita do frame pai, e 0% de cima para baixo do frame pai).
- Defina Size para {1, 0},{0.67, 0} para que os componentes da UI de seleção ocupem mais da metade do contêiner de cima para baixo (100% horizontalmente e 67% verticalmente do frame pai).
- Defina Name para ObjectiveDisplay.

Crie os elementos do título.
Insira um ImageLabel no ObjectiveDisplay.
Selecione o ImageLabel, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 1 para definir o ponto de origem do rótulo na parte inferior do meio (50% da esquerda para a direita do rótulo, e 100% de cima para baixo do rótulo).
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina LayoutOrder para -1.
- Defina Position para {0.5, 0},{0.34, 0} para posicionar o rótulo próximo ao topo da parte superior do frame (50% da esquerda para a direita do frame pai, e 34% de cima para baixo do frame pai).
- Defina Size para {0.46, 0},{0.34, 0} para ampliar a área do prompt para quase metade do frame (46% horizontalmente e 34% verticalmente do frame pai).
- Defina Name para Header.
- Defina Image para rbxassetid://14304828123 para exibir um trapézio.
- Defina ImageTransparency para 0.15 para tornar o cabeçalho semitransparente.

(Opcional) Insira um UIAspectRatioConstraint no ImageLabel para garantir que a proporção do rótulo permaneça a mesma, independentemente do tamanho da tela do jogador. A amostra define sua propriedade UIAspectRatioConstraint.AspectRatio para 13.781.
Insira um TextLabel no Header para exibir um título.
Selecione o novo rótulo, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do novo rótulo no meio (50% da esquerda para a direita do rótulo, e 50% de cima para baixo do rótulo).
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina Position para {0.5, 0},{0.5, 0} para mover o rótulo para o meio do seu rótulo pai (50% da esquerda para a direita do rótulo pai, e 50% de cima para baixo do rótulo pai).
- Defina Size para {0.62, 0},{0.55, 0} para ampliar o espaço do texto para mais da metade do rótulo pai (62% horizontalmente e 55% verticalmente do rótulo pai).
- Defina Name para HeaderTextLabel.
- Defina FontFace para Montserrat para se adequar à estética futurista.
- Defina Weight para Medium para engrossar a fonte.
- Defina Text para OBJECTIVO.
- Habilite TextScaled.

Crie os elementos de prompt.
Insira um ImageLabel no ObjectiveDisplay.
Selecione o ImageLabel, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 1 para definir o ponto de origem do rótulo na parte inferior do meio (50% da esquerda para a direita do rótulo, e 100% de cima para baixo do rótulo).
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina Position para {0.5, 0},{1, 0} para mover o rótulo para o fundo do meio do seu frame pai (50% da esquerda para a direita do frame pai, e 100% de cima para baixo do frame pai).
- Defina Size para {0.89, 0},{0.66, 0} para ampliar o espaço do texto para quase a largura total do frame pai (89% horizontalmente e 66% verticalmente do frame pai).
- Defina Name para Body.
- Defina Image para rbxassetid://14304827265 para exibir um trapézio invertido.
- Defina ImageColor3 para 0, 0, 0 para tingir a imagem de preto.
- Defina ImageTransparency para 0.3 para tornar o cabeçalho semitransparente.

(Opcional) Insira um UIAspectRatioConstraint no ImageLabel para garantir que a proporção do rótulo permaneça a mesma, independentemente do tamanho da tela do jogador. A amostra define sua propriedade UIAspectRatioConstraint.AspectRatio para 13.781.
Insira um TextLabel no Body para exibir um prompt.
Selecione o novo rótulo, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do novo rótulo no meio (50% da esquerda para a direita do rótulo, e 50% de cima para baixo do rótulo).
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina Position para {0.5, 0},{0.5, 0} para mover o rótulo para o meio do seu rótulo pai (50% da esquerda para a direita do rótulo pai, e 50% de cima para baixo do rótulo pai).
- Defina Size para {0.85, 0},{0.39, 0} para ampliar o espaço do texto para mais da metade do rótulo pai (85% horizontalmente e 39% verticalmente do rótulo pai).
- Defina Name para BodyTextLabel.
- Defina FontFace para Montserrat para se adequar à estética futurista.
- Defina Weight para Medium para engrossar a fonte.
- Defina TextColor3 para 255, 255, 255 para tornar o texto branco contra o fundo escuro.
- Defina Text para Tag opponents to score points! First team to %d points wins..
- Habilite TextScaled.

Crie um contêiner para os contadores de equipe do objetivo.
Insira um Frame no Objective.
Selecione o novo Frame, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 1 para definir o ponto de origem do rótulo na parte inferior do meio (50% da esquerda para a direita do frame, e 100% de cima para baixo do frame).
- Defina BackgroundTransparency para 1 para tornar o fundo do frame completamente transparente.
- Defina Position para {0.5, 0},{1, 0} para posicionar o frame na parte inferior do meio do contêiner (50% da esquerda para a direita do frame pai, e 100% de cima para baixo do frame pai).
- Defina Size para {0.44, 0},{0.27, 0} para que os componentes da UI de seleção ocupem cerca de menos da metade do contêiner da esquerda para a direita (44% horizontalmente e 27% verticalmente do frame pai).
- Defina Name para TeamPointCounter.

Crie o preenchimento para os contadores de equipe.
- Insira um objeto UIListLayout no frame do passo 5.
- Selecione o objeto UIListLayout, e na janela Propriedades,
- Defina Padding para 0.025, 0 para fornecer espaço entre os futuros contadores de equipe.
- Defina FillDirection para Horizontal para que cada contador de equipe seja exibido lado a lado.
- Defina HorizontalAlignment para Center para que cada contador de equipe se alinhe ao meio um do outro.
Crie os elementos do contador da equipe verde.
Insira um ImageLabel no TeamPointCounter.
Selecione o ImageLabel, e na janela Propriedades,
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina Position para {0.5, 0},{1, 0} para mover o rótulo para a parte inferior do meio do seu frame pai (50% da esquerda para a direita do frame pai, e 100% de cima para baixo do frame pai).
- Defina Size para {0.5, 0},{1, 0} para ampliar o rótulo para a metade da largura do frame pai (50% horizontalmente e 100% verticalmente do frame pai).
- Defina Name para TeamACounter.
- Defina Image para rbxassetid://14304826831 para exibir um fade direcional.
- Defina ImageColor3 para 88, 218, 171 para tingir a imagem verde menta.

Configure um atributo personalizado para rastrear que este rótulo é para a equipe verde.
- Na janela Propriedades, navegue até a seção Atributos, e clique no ícone de mais. Um diálogo pop-up é exibido.
- No campo Nome, insira teamColor.
- No menu suspenso Tipo, selecione BrickColor.
- Clique no botão Salvar.
- Defina o novo atributo teamColor para Mint.
Insira um TextLabel no TeamACounter para exibir um prompt.
Selecione o novo rótulo, e na janela Propriedades,
- Defina AnchorPoint para 1, 0.5 para definir o ponto de origem do novo rótulo na parte direita do meio (100% da esquerda para a direita do rótulo, e 50% de cima para baixo do rótulo).
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina Position para {0.95, 0},{0.5, 0} para mover o rótulo para a direita do seu rótulo pai (95% da esquerda para a direita do rótulo pai, e 50% de cima para baixo do rótulo pai).
- Defina Size para {0.85, 0},{0.39, 0} para ampliar o espaço do texto para mais da metade do rótulo pai (85% horizontalmente e 39% verticalmente do rótulo pai).
- Defina FontFace para Montserrat para se adequar à estética futurista.
- Defina Weight para Bold para engrossar a fonte.
- Defina TextColor3 para 255, 255, 255 para tornar o texto branco contra o fundo escuro.
- Defina Text para -.
- Habilite TextScaled.
- Defina TextXAlignment para Right.

Insira um objeto UIStroke no TextLabel, e na janela Propriedades, defina Color para 8, 78, 52 para contornar o traço com um contorno verde escuro.

Crie os elementos do contador da equipe rosa.
Duplique TeamAICounter e seus filhos.
Selecione a duplicata TeamACounter, e na janela Propriedades,
- Defina Name para TeamBCounter.
- Defina Image para rbxassetid://14305849451 para exibir um fade direcional na direção oposta.
- Defina ImageColor3 para 255, 170, 255 para tingir a imagem de rosa carnation.
- Defina o atributo teamColor para Carnation Pink.
Selecione a duplicata TextLabel filha de TeamBCounter, e na janela Propriedades,
- Defina AnchorPoint para 0, 0.5 para definir o ponto de origem do novo rótulo na parte esquerda do meio (0% da esquerda para a direita do rótulo, e 50% de cima para baixo do rótulo).
- Defina Position para {0.05, 0},{0.5, 0} para mover o rótulo para a esquerda do seu rótulo pai (5% da esquerda para a direita do rótulo pai, e 50% de cima para baixo do rótulo pai).
- Defina TextXAlignment para Left.
Selecione a duplicata UIStroke filha de TeamBCounter, e na janela Propriedades, defina Color para 158, 18, 94 para contornar o traço com um contorno rosa escuro.

Referencie os seguintes scripts de ReplicatedStorage dentro do arquivo de lugar da amostra Laser Tag que atualizam programaticamente o prompt do objetivo e rastreiam os pontos da equipe.
O seguinte script requer um conjunto de scripts de módulo que trabalham juntos para configurar o principal Display Heads Up (HUD), incluindo setObjective e startSyncingTeamPoints. Após um jogador entrar em uma rodada e selecionar seu blaster, este script garante que todos os elementos de UI do HUD sejam exibidos adequadamente de acordo com o estado do jogador, dispositivo e status da equipe.
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.LocalPlayerlocal gui = localPlayer.PlayerGui:WaitForChild("HUDGui")setPlayerPortrait(gui)setPlayerName(gui)startSyncingTeamColor(gui)setObjective(gui)startSyncingTeamPoints(gui)disableMouseWhileGuiEnabled(gui)setupHitmarker(gui)setupTouchButtonAsync(gui)
UI do Blaster
Seguindo as melhores práticas de hierarquia visual do Wireframe Your Layouts, esta seção ensina como implementar todos os elementos de UI na tela relacionados ao blaster do jogador. Este agrupamento de elementos de UI ocupa a maior parte do espaço da tela perto do centro porque atua como o ponto focal para chamar a atenção dos jogadores para a ação no espaço 3D, e tem a maior significância para jogar o jogo.

Retículo
Um retículo é um elemento de UI que informa os jogadores onde eles vão causar impacto quando dispararem sua arma. Este elemento de UI é um requisito vital de jogabilidade para experiências de tiro em primeira pessoa porque os jogadores precisam ser capazes de mirar com precisão seu blaster e eliminar membros da equipe adversária.
Como a maioria das outras experiências no gênero de tiro em primeira pessoa, a experiência de laser tag de amostra posiciona o retículo no centro da tela para que os jogadores tenham algo estático para focar enquanto seu avatar se move pelo espaço 3D. Além de reduzir o enjoo, este posicionamento permite que o retículo seja perceptível enquanto também se mistura ao ambiente geral.

Para recriar exatamente o retículo dentro da amostra Laser Tag:
Insira um ImageLabel no objeto HUDGui ScreenGui.
Na janela Explorador, navegue até o serviço StarterGui.
Passe o mouse sobre seu objeto filho HUDGui, e clique no ícone ⊕. Um menu contextual é exibido.
No menu contextual, insira um ImageLabel.

Selecione o novo ImageLabel, e na janela Propriedades,
- Defina Image para rbxassetid://14400935446.
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do rótulo no meio do rótulo (50% da esquerda para a direita do rótulo, e 50% de cima para baixo do rótulo).
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina Name para Crosshair.
- Defina Position para {0.5,0},{0.5,0} para posicionar o rótulo no meio da tela.
- Defina ScaleType para Fit para que a imagem se encaixe dentro de seu contêiner e não estique em vários tamanhos de tela.
(Opcional) Insira um UIAspectRatioConstraint no Crosshair para garantir que a proporção do rótulo permaneça a mesma, independentemente do tamanho da tela do jogador. A amostra define sua propriedade UIAspectRatioConstraint.AspectRatio para 0.895.
Marcador de Acerto
Um marcador de acerto é um elemento de UI que só é exibido quando um disparo atinge outro jogador da equipe adversária. Assim como o retículo, este elemento de UI é um requisito vital de jogabilidade para experiências de tiro em primeira pessoa porque fornece feedback visual de quando os jogadores têm sucesso ao eliminar seus oponentes.

Para recriar exatamente o marcador de acerto dentro da amostra Laser Tag:
Insira um ImageLabel no objeto Crosshair ImageLabel.
Na janela Explorador, navegue até o serviço StarterGui.
Passe o mouse sobre seu objeto filho Crosshair, e clique no ícone ⊕. Um menu contextual é exibido.
No menu contextual, insira um ImageLabel.

Selecione o novo ImageLabel, e na janela Propriedades,
- Defina Image para rbxassetid://14401148736 para exibir o ícone retangular do marcador de acerto.
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do rótulo no meio do rótulo.
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina Position para {0.5,0},{0.5,0} para posicionar o rótulo no meio da tela.
- Defina Name para Hitmarker.
- Defina Size para {0.6, 0},{0.06, 0} para reduzir o tamanho dos retângulos ao redor do meio do retículo.
- Defina ImageTransparency para 1 para tornar o marcador de acerto completamente transparente. Os scripts na próxima etapa reverterão a transparência de volta a 0 toda vez que o disparo de um jogador atingir outro jogador da equipe adversária.
Referencie os seguintes scripts de ReplicatedStorage dentro do arquivo de lugar da amostra Laser Tag que exibem programaticamente o marcador de acerto quando um disparo atinge um jogador da equipe adversária.
O seguinte script requer um conjunto de scripts de módulo que trabalham juntos para configurar o principal Display Heads Up (HUD), incluindo setupHitmarker. Após um jogador entrar em uma rodada e selecionar seu blaster, este script garante que todos os elementos de UI do HUD sejam exibidos adequadamente de acordo com o estado do jogador, dispositivo e status da equipe.
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.LocalPlayerlocal gui = localPlayer.PlayerGui:WaitForChild("HUDGui")setPlayerPortrait(gui)setPlayerName(gui)startSyncingTeamColor(gui)setObjective(gui)startSyncingTeamPoints(gui)disableMouseWhileGuiEnabled(gui)setupHitmarker(gui)setupTouchButtonAsync(gui)
Seletor de Blaster
Um seletor de blaster é um componente de UI que os jogadores usam para selecionar seu tipo de blaster antes de entrar ou reentrar em uma rodada. A experiência de laser tag de amostra fornece dois tipos de blasters: um que produz vários feixes com uma ampla dispersão horizontal e outro que produz um único feixe. O tipo de blaster que os jogadores selecionam influencia sua estratégia durante a rodada, tornando este componente de UI um fluxo de trabalho essencial para a experiência geral.
Os seguintes passos detalham como criar vários contêineres para os diferentes agrupamentos de elementos de UI, um cabeçalho com um prompt, os botões de navegação e seleção e um prefab de botão de blaster. A lógica de script para o componente geral preenche diferentes características visuais no prefab do botão de blaster de acordo com as instâncias de Configuration que representam cada tipo de blaster.
Essa configuração permite que você crie instâncias adicionais de Configuration para mais tipos de blaster que se exibem automaticamente corretamente dentro do seletor de blaster, sem precisar criar botões individuais dentro de StarterGui.PickABlasterGui.

Para recriar exatamente o seletor de blaster dentro da amostra Laser Tag:
Crie um contêiner para todo o componente.
Insira um Frame no objeto PickABlaster ScreenGui.
- Na janela Explorador, navegue até o serviço StarterGui.
- Passe o mouse sobre seu objeto filho PickABlaster, e clique no ícone ⊕. Um menu contextual é exibido.
- No menu contextual, insira um Frame.

Selecione o novo frame, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 1 para definir o ponto de origem do frame na parte inferior do meio (50% da esquerda para a direita do frame, e 100% de cima para baixo do frame).
- Defina BackgroundTransparency para 1 para tornar o fundo do frame completamente transparente.
- Defina Position para {0.5, 0},{0.9, 0} para posicionar o frame próximo à parte inferior do meio da tela (50% da esquerda para a direita da tela, e 92.4% de cima para baixo da tela).
- Defina Size para {0.8, 0},{0.25, 0} para que os componentes de UI do seletor de blaster ocupem uma grande parte da tela para chamar a atenção dos jogadores (80% horizontalmente, e 25% verticalmente).
- Defina Name para Component.

(Opcional) Insira um UIAspectRatioConstraint no Component para garantir que a proporção do frame e de seus elementos de UI filhos permaneça a mesma, independentemente do tamanho da tela do jogador. A amostra define sua propriedade UIAspectRatioConstraint.AspectRatio para 5.
Crie um contêiner para manter os agrupamentos de elementos de UI.
Insira um Frame no Component.
Selecione o novo frame, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do frame no meio (50% da esquerda para a direita do frame, e 50% de cima para baixo do frame).
- Defina BackgroundTransparency para 1 para tornar o fundo do frame completamente transparente.
- Defina Position para {0.5, 0},{0.375, 0} para posicionar o frame próximo ao topo do meio do contêiner (50% da esquerda para a direita do frame pai, e 37.5% de cima para baixo do frame pai).
- Defina Size para {1, 0},{0.75, 0} para que os componentes de UI de seleção ocupem 3/4 do contêiner (100% horizontalmente e 75% verticalmente do frame pai).
- Defina Name para SelectionFrame.

Crie um prompt para o seletor de blaster.
Insira um ImageLabel no SelectionFrame.
Selecione o novo rótulo, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 1 para definir o ponto de origem do rótulo na parte inferior do meio (50% da esquerda para a direita do rótulo, e 100% de cima para baixo do rótulo).
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina LayoutOrder para -1.
- Defina Position para {0.5, 0},{0.22, 0} para posicionar o rótulo próximo ao topo da parte superior do frame (50% da esquerda para a direita do frame pai, e 22% de cima para baixo do frame pai).
- Defina Size para {0.45, 0},{0.22, 0} para ampliar a área do prompt para quase metade do frame (45% horizontalmente e 22% verticalmente do frame pai).
- Defina Name para Header.
- Defina Image para rbxassetid://14304828123 para exibir um trapézio.
- Defina ImageTransparency para 0.15 para tornar o cabeçalho semitransparente.

(Opcional) Insira um UIAspectRatioConstraint no rótulo para garantir que a proporção do rótulo permaneça a mesma, independentemente do tamanho da tela do jogador. A amostra define sua propriedade UIAspectRatioConstraint.AspectRatio para 13.78.
Insira um TextLabel no Header para exibir um prompt.
Selecione o novo rótulo, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do novo rótulo no meio (50% da esquerda para a direita do rótulo, e 50% de cima para baixo do rótulo).
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina Position para {0.5, 0},{0.5, 0} para mover o rótulo para o meio do seu rótulo pai (50% da esquerda para a direita do rótulo pai, e 50% de cima para baixo do rótulo pai).
- Defina Size para {0.6, 0},{0.55, 0} para ampliar o espaço do texto para mais da metade do seu rótulo pai (60% horizontalmente e 55% verticalmente do rótulo pai).
- Defina Name para HeaderTextLabel.
- Defina FontFace para Montserrat para se adequar à estética futurista.
- Defina Weight para Medium para engrossar a fonte.
- Defina Text para ESCOLHA UM BLASTER.
- Habilite TextScaled.

Crie o contêiner para o contêiner do botão de blaster e as setas de seleção.
Insira um ImageLabel no SelectionFrame.
Selecione o novo rótulo, e na janela Propriedades,
- Remova o valor padrão de Image.
- Defina AnchorPoint para 0.5, 1 para definir o ponto de origem do rótulo na parte inferior do meio (50% da esquerda para a direita do rótulo, e 100% de cima para baixo do rótulo).
- Defina BackgroundColor para 0, 0, 0 para tornar o rótulo preto.
- Defina BackgroundTransparency para 0.3 para reduzir a opacidade do rótulo em 30%, e combinar com todos os elementos de UI pretos na experiência.
- Defina Position para {0.5, 0},{1, 0} para posicionar o rótulo na parte inferior do meio do frame (50% da esquerda para a direita do frame pai, e 100% de cima para baixo do frame pai).
- Defina Size para {1, 0},{0.77, 0} para ampliar a área do rótulo para o espaço abaixo do prompt (100% horizontalmente e 77% verticalmente do frame pai).

Arredonde os cantos do contêiner.
- Insira um objeto UICorner no rótulo.
- Selecione o novo objeto de canto, e na janela Propriedades, defina CornerRadius para 0.075, 0 para arredondar os cantos.

Crie o contêiner para seus botões de blaster.
Insira um Frame no rótulo da etapa 4.
Selecione o novo frame, e na janela Propriedades,
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do novo frame no meio (50% da esquerda para a direita do frame, e 50% de cima para baixo do frame).
- Defina BackgroundTransparency para 1 para tornar o fundo do frame completamente transparente.
- Defina Position para {0.5, 0},{0.5, 0} para posicionar o frame no meio do seu rótulo pai (50% da esquerda para a direita do frame pai, e 50% de cima para baixo do frame pai).
- Defina Size para {0.85, 0},{0.77, 0} para ampliar a área do frame para a maior parte do rótulo (85% horizontalmente e 77% verticalmente do rótulo pai).
- Defina Name para Container.

Crie o preenchimento para todos os futuros botões de blaster.
- Insira um objeto UIListLayout no frame da etapa 5.
- Selecione o novo objeto de layout, e na janela Propriedades,
- Defina Padding para 0.035, 0 para fornecer espaço entre todos os futuros botões.
- Defina FillDirection para Horizontal para que cada botão seja exibido lado a lado.
- Defina HorizontalAlignment e VerticalAlignment para Center para que cada botão se alinhe ao meio um do outro.
Crie o botão de navegação esquerdo.
Insira um objeto ImageButton no ImageLabel da etapa 4.
Selecione o novo botão, e na janela Propriedades,
- Remova o valor padrão de Image.
- Defina AnchorPoint para 0, 0.5 para definir o ponto de origem do novo botão na parte esquerda do meio (0% da esquerda para a direita do botão, e 50% de cima para baixo do botão).
- Defina BackgroundTransparency para 0.15 para fornecer feedback visual ao passar o mouse que o botão é selecionável.
- Defina Position para {0.02, 0},{0.5, 0} para fornecer preenchimento à esquerda do botão em relação ao seu contêiner pai (2% da esquerda para a direita do rótulo pai, e 50% de cima para baixo do rótulo pai).
- Defina Size para {0.04, 0},{0.33, 0} para tornar o botão de seleção muito menor do que os botões de blaster (4% horizontalmente e 33% verticalmente do frame pai).
- Defina Name para NavigationButtonLeft.

Arredonde os cantos do botão.
- Insira um objeto UICorner no botão.
- Selecione o novo objeto de canto e, na janela Propriedades, defina CornerRadius como 0.1, 0 para arredondar os cantos.

Insira um objeto ImageLabel no botão.
Selecione a nova etiqueta e, na janela Propriedades,
- Defina AnchorPoint como 0.5, 0.5 para definir o ponto de origem da nova etiqueta no meio dela (50% da esquerda para a direita da etiqueta, e 50% de cima para baixo da etiqueta).
- Defina Position como {0.45, 0},{0.5, 0} para posicionar a etiqueta próxima ao meio de seu botão pai (45% da esquerda para a direita do botão pai, e 50% de cima para baixo do botão pai). Este valor não está no meio porque uma seta não parece visualmente estar no meio do botão em {0.5, 0},{0.5, 0}.
- Defina Size como {0.8, 0},{0.8, 0} para alargar a área da etiqueta e se estender abaixo do prompt (80% horizontalmente e 80% verticalmente do quadro pai).
- Defina BackgroundTransparency como 1 para tornar o fundo da imagem completamente transparente.
- Defina Image como rbxassetid://14309187238.
- Defina ScaleType como Fit.

Crie o botão de navegação da direita.
Duplicar NavigationButtonLeft.
Selecione o botão duplicado e, na janela Propriedades,
- Defina AnchorPoint como 1, 0.5 para definir o ponto de origem do novo botão no meio da direita dele (100% da esquerda para a direita do botão, e 50% de cima para baixo do botão).
- Defina Position como {0.98, 0},{0.5, 0} para fornecer espaçamento na direita do botão em relação ao seu contêiner pai (98% da esquerda para a direita do rótulo pai, e 50% de cima para baixo do rótulo pai).
- Defina Name como NavigationButtonRight.
Selecione seu objeto filho ImageLabel.
- Defina Rotation como 180 para girar a imagem.
- Defina Position como {0.55, 0},{0.5, 0} para posicionar a etiqueta próxima ao meio de seu botão pai (55% da esquerda para a direita do botão pai, e 50% de cima para baixo do botão pai). Este valor não está no meio porque uma seta não parece visualmente estar no meio do botão em {0.5, 0},{0.5, 0}.

Crie o botão SELECT.
Insira um ImageButton em Component. Note como esse processo mantém o botão de seleção separado de SelectionFrame para que você possa adicionar espaçamento entre a parte principal do componente e o botão de seleção.
Selecione o novo botão e, na janela Propriedades,
- Remova o valor padrão Image.
- Defina AnchorPoint como 0.5, 1 para definir o ponto de origem do novo botão na parte inferior do meio dele (50% da esquerda para a direita do botão, e 100% de cima para baixo do botão).
- Defina BackgroundTransparency como 0.15 para fornecer feedback visual ao passar o mouse que o botão é selecionável.
- Defina Position como {0.5, 0},{0.99, 0} para posicionar o botão próximo ao meio inferior de seu contêiner (50% da esquerda para a direita do quadro pai, e 99% de cima para baixo do quadro pai).
- Defina Size como {0.17, 0},{0.18, 0} para alargar o botão abaixo dos botões de disparo (17% horizontalmente e 18% verticalmente do quadro pai).
- Defina Name como SelectButton.

Arredonde os cantos do botão.
- Insira um objeto UICorner no botão.
- Selecione o novo objeto de canto e, na janela Propriedades, defina CornerRadius como 0.2, 0 para arredondar os cantos.

Insira um objeto TextLabel no botão para exibir uma chamada à ação.
Selecione a nova etiqueta e, na janela Propriedades,
- Defina AnchorPoint como 0.5, 0.5 para definir o ponto de origem da nova etiqueta no meio dela (50% da esquerda para a direita da etiqueta, e 50% de cima para baixo da etiqueta).
- Defina BackgroundTransparency como 1 para tornar o fundo da etiqueta completamente transparente.
- Defina Position como {0.5, 0},{0.5, 0} para mover a etiqueta para o meio do botão (50% da esquerda para a direita do botão pai, e 50% de cima para baixo do botão pai).
- Defina Size como {0.9, 0},{0.55, 0} para alargar o espaço do texto para quase toda a largura do rótulo pai (90% horizontalmente e 55% verticalmente do rótulo pai).
- Defina Name como SelectTextLabel.
- Defina FontFace como Montserrat para se adequar à estética futurista.
- Defina Weight como Medium para engrossar a fonte.
- Defina Text como SELECT.
- Ative TextScaled.

Crie um prefab do botão blaster.
- No serviço ReplicatedStorage, crie uma estrutura de pastas para organizar seus objetos de UI. O exemplo usa uma pasta Instances com uma pasta filha Guis.
- Insira um objeto ImageButton na pasta Guis.
- Selecione o novo botão e, na janela Propriedades,
- Remova o valor padrão Image.
- Defina AnchorPoint como 0.5, 0.5 para definir o ponto de origem do novo botão no meio dele (50% da esquerda para a direita do botão, e 50% de cima para baixo do botão).
- Defina BackgroundTransparency como 0.65 para fornecer feedback visual de que o botão não está em foco. Scripts na etapa 12 fornecem feedback visual programático quando o botão estiver em foco.
- Defina LayoutOrder como 2.
- Defina Name como BlasterButtonPrefab.
- Defina Size como {0.8, 0},{0.8, 0}.
- Defina ImageTransparency como 1 para tornar a imagem completamente transparente.
- Insira um UIAspectRatioConstraint em BlasterButtonPrefab para garantir que a proporção do botão permaneça a mesma dentro do componente, independentemente do tamanho da tela do jogador.
- Arredonde os cantos do botão.
- Insira um objeto UICorner em BlasterButtonPrefab.
- Selecione o UICorner e, na janela Propriedades, defina CornerRadius como 0.05, 0 para arredondar os cantos.
- Insira um ImageLabel em BlasterButtonPrefab.
- Selecione a nova etiqueta e, na janela Propriedades,
- Remova o valor padrão Image.
- Defina AnchorPoint como 0.5, 0.5 para definir o ponto de origem da nova etiqueta no meio dela (50% da esquerda para a direita da etiqueta, e 50% de cima para baixo da etiqueta).
- Defina BackgroundTransparency como 1 para tornar o fundo da etiqueta completamente transparente.
- Defina Position como {0.52, 0},{0.497, 0} para posicionar a etiqueta próxima ao meio de seu botão pai (52% da esquerda para a direita do botão pai, e 49.7% de cima para baixo do botão pai). Este valor não está no meio porque o blaster não parece visualmente estar no meio do botão em {0.5, 0},{0.5, 0}.
- Defina Size como {1.20, 0},{0.9, 0} para alargar a área da etiqueta fora do botão (120% horizontalmente e 90% verticalmente do botão pai).
- Defina ScaleType como Fit.
Referencie os seguintes scripts ReplicatedStorage dentro do arquivo de lugar exemplo Laser Tag que exibem programaticamente botões para cada blaster, escalam os botões quando um jogador seleciona um botão que não está em foco e anexam a seleção do blaster de um jogador ao seu avatar.
O seguinte script requer um conjunto de scripts que trabalham juntos para criar o seletor de blasters. Quando um jogador entra na experiência ou renasce após sua saúde chegar a zero, este script ativa todos os elementos de UI do seletor de blasters até que o jogador faça sua seleção.
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.LocalPlayerlocal gui = localPlayer.PlayerGui:WaitForChild("PickABlasterGui")setupBlasterButtons(gui)connectResetSelectionOnEnabled(gui)gui:SetAttribute(GuiAttribute.selectedIndex, 1)
Botão de disparo
Um botão de disparo é um componente de UI que os jogadores usam para disparar seu blaster se estiverem acessando a experiência através de um dispositivo móvel ou tablet. A experiência de laser tag de exemplo usa um botão de disparo com um ícone que retrata tanto uma mira quanto um disparo para comunicar a função do botão sem texto.

Para reproduzir exatamente o botão de disparo dentro da experiência de exemplo Laser Tag:
Insira um ImageButton no objeto HUDGui ScreenGui.
Na janela Explorer, navegue até o serviço StarterGui.
Passe o mouse sobre seu objeto filho HUDGui e clique no ícone ⊕. Um menu contextual é exibido.
No menu contextual, insira um ImageButton.

No viewport, mova o botão para onde o polegar de um jogador repousa naturalmente, para que você possa obter uma ideia visual de como o botão ficará no dispositivo de um jogador e, em seguida, na janela Propriedades,
- Defina Image como rbxassetid://18308375035 para exibir o ícone do botão de disparo.
- Defina PressedImage como rbxassetid://18308372558 para exibir uma versão invertida do ícone do botão de disparo quando um jogador pressiona o botão.
- Defina BackgroundTransparency como 1 para tornar o fundo da etiqueta completamente transparente.
- Defina Name como BlastButton.
- Defina ScaleType como Fit para que a imagem caiba dentro de seu contêiner e não estique em vários tamanhos de tela.
- Defina ImageTransparency como 0.3 para reduzir a opacidade da etiqueta para que ela combine com todos os elementos de UI pretos na experiência.
Insira um UIAspectRatioConstraint em BlastButton para garantir que a proporção do botão permaneça a mesma, independentemente do tamanho da tela do jogador.
Referencie os seguintes scripts ReplicatedStorage dentro do arquivo de lugar exemplo Laser Tag que exibem programaticamente o botão de disparo quando um jogador está usando entrada de toque em um dispositivo que aceita controles de toque.
O seguinte script requer um conjunto de scripts de módulo que trabalham juntos para configurar o principal Heads Up Display (HUD), incluindo setupTouchButtonAsync. Após um jogador entrar em uma rodada e selecionar seu blaster, este script garante que todos os elementos de UI do HUD sejam exibidos adequadamente para o estado, dispositivo e status da equipe do jogador.
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.LocalPlayerlocal gui = localPlayer.PlayerGui:WaitForChild("HUDGui")setPlayerPortrait(gui)setPlayerName(gui)startSyncingTeamColor(gui)setObjective(gui)startSyncingTeamPoints(gui)disableMouseWhileGuiEnabled(gui)setupHitmarker(gui)setupTouchButtonAsync(gui)
UI do Jogador
Seguindo as melhores práticas de hierarquia visual do Wireframe Your Layouts, esta seção ensina como implementar todos os elementos de UI na tela relacionados ao estado do jogador. Este agrupamento de elementos de UI está próximo aos lados da tela porque os jogadores podem compreender essas informações periféricas sem desviar a atenção do jogo.

Indicador do jogador
Um indicador do jogador é um componente de UI que os jogadores referenciam para decifrar rapidamente a que equipe pertencem assim que entrarem na zona de spawn de sua equipe. A experiência de laser tag de exemplo fornece duas versões do indicador do jogador dependendo se o jogador está na equipe verde ou rosa.


Seguindo as orientações de Selecionar um Tema de Cor, ambas as versões do indicador do jogador combinam a cor da equipe com um ícone único e simples com detalhes mínimos para que permaneçam legíveis em telas pequenas. Fornecer duas formas de feedback visual é importante porque ajuda a manter o design acessível para jogadores com daltonismo.

Para reproduzir exatamente o componente do indicador do jogador dentro da experiência de exemplo Laser Tag:
Insira um Frame no objeto HUDGui ScreenGui.
- Na janela Explorer, navegue até o serviço StarterGui.
- Passe o mouse sobre seu objeto filho HUDGui e clique no ícone ⊕. Um menu contextual é exibido.
- No menu contextual, insira um Frame.
Selecione o novo Frame e, na janela Propriedades,
Defina AnchorPoint como 0, 1 para definir o ponto de origem do quadro na parte inferior do meio dele (0% da esquerda para a direita do quadro e 100% de cima para baixo do quadro).
Defina BackgroundTransparency como 1 para tornar o fundo da etiqueta completamente transparente.
Defina Name como PlayerDisplay.
Defina Position como {0.02, 0},{0.97, 0} para posicionar o quadro próximo à parte inferior esquerda da tela.
Defina Size como {0.23, 0},{0.08, 0} para encurtar e alargar o quadro.
Ative ClipsDescendants para aparar objetos Gui de filha que se estendem além do quadro.

Crie a forma poligonal.
Insira um ImageLabel dentro de PlayerDisplay.
Selecione a nova etiqueta e, na janela Propriedades,
- Defina Image como rbxassetid://14304828123 para exibir o ícone do trapézio.
- Defina AnchorPoint como 1, 1 para definir o ponto de origem da etiqueta na parte inferior direita dela (100% da esquerda para a direita da etiqueta e 100% de cima para baixo da etiqueta).
- Defina BackgroundTransparency como 1 para tornar o fundo da etiqueta completamente transparente.
- Defina Name como Block.
- Defina Position como {1,0},{1,0} para posicionar a etiqueta do lado direito do quadro.
- Defina Size como {1.858, 0},{0.581, 0} para alargar a etiqueta fora do quadro e encurtá-la para um pouco mais da metade do tamanho do quadro.
- Defina ImageTransparency como 0.15 para tornar a etiqueta ligeiramente transparente.
- Defina ScaleType como Fit para que a imagem se ajuste dentro de seu contêiner e não se estique em vários tamanhos de tela.

- Insira um UIAspectRatioConstraint em Block para garantir que a proporção da etiqueta e de seus elementos de UI filhos permaneça a mesma, independentemente do tamanho da tela do jogador.
- Selecione a nova restrição e, na janela Propriedades, defina AspectRatio como 13.78.
Crie a caixa para o retrato do jogador.
Insira um ImageLabel dentro de PlayerDisplay.
Selecione a nova etiqueta e, na janela Propriedades,
- Remova o ID do ativo padrão dentro da propriedade Image. Os scripts na etapa 7 inserem programaticamente o retrato do jogador na etiqueta de imagem.
- Defina AnchorPoint como 0, 1 para definir o ponto de origem da etiqueta na parte inferior esquerda dela (0% da esquerda para a direita da etiqueta e 100% de cima para baixo da etiqueta).
- Defina BackgroundColor3 como 0, 0, 0 para definir a cor de fundo da etiqueta como preta.
- Defina BackgroundTransparency como 0.3 para reduzir a opacidade da etiqueta em 30% e combinar com todos os elementos de UI pretedos na experiência.
- Defina Name como PlayerPortrait.
- Defina Position como {0.11, 0},{1, 0} para posicionar a etiqueta do lado esquerdo da forma poligonal.
- Defina Size como {0.23, 0},{1, 0} para encolher a etiqueta.
- Defina ImageTransparency como 0.15 para tornar a etiqueta ligeiramente transparente.
- Defina ScaleType como Fit para que a imagem se ajuste dentro de seu contêiner e não se estique em vários tamanhos de tela.

- Insira um UIAspectRatioConstraint em PlayerPortrait para garantir que a proporção da etiqueta e de seus elementos de UI filhos permaneça a mesma, independentemente do tamanho da tela do jogador.
- Insira um UICorner em PlayerPortrait e, na janela Propriedades, defina CornerRadius como 0.05, 0 para arredondar ligeiramente os cantos.

Crie a etiqueta de texto para o nome do jogador.
Insira um objeto TextLabel em PlayerDisplay.
Selecione a nova etiqueta e, na janela Propriedades,
- Defina AnchorPoint como 0, 0.5 para definir o ponto de origem do novo botão na parte esquerda do meio dele (0% da esquerda para a direita do botão e 50% de cima para baixo do botão).
- Defina BackgroundTransparency como 1 para tornar o fundo da etiqueta completamente transparente.
- Defina Name como PlayerNameTextLabel.
- Defina Position como {0.35, 0},{0.72, 0} para posicionar a etiqueta do lado direito de seu contêiner (35% da esquerda para a direita do rótulo pai e 72% de cima para baixo do rótulo pai).
- Defina Size como {0.52, 0},{0.3, 0} para que o texto ocupe a maior parte da área da forma poligonal (52% horizontalmente e 30% verticalmente do quadro pai).
- Defina FontFace como Montserrat para se adequar à estética futurista.
- Defina Weight como Bold para engrossar a fonte.
- Remova o texto de espaço reservado dentro da propriedade Text. Os scripts na etapa 7 inserem programaticamente o nome do jogador na etiqueta de texto.
- Ative TextScaled.
- Defina TextXAlignment como Left.

Crie os ícones e cores da equipe que serão exibidos à esquerda do retrato do jogador.
Insira uma Pasta dentro de PlayerDisplay e renomeie para TeamIcons.
Crie o ícone e a cor da equipe verde.
- Insira um ImageLabel dentro de TeamIcons.
- Selecione a nova etiqueta e, na janela Propriedades,
- Defina AnchorPoint como 0, 1 para definir o ponto de origem da etiqueta na parte inferior esquerda dela (0% da esquerda para a direita da etiqueta e 100% de cima para baixo da etiqueta).
- Defina BackgroundColor3 como 88, 218, 171 para definir a cor de fundo da etiqueta como verde mint.
- Defina Name como TeamAIcon.
- Defina Position como {0, 0},{1, 0} para posicionar a etiqueta do lado esquerdo do quadro.
- Defina Size como {0.135, 0},{0.58, 0} para encolher a etiqueta para o lado esquerdo do retrato do jogador.
- Defina ImageTransparency como 1 para tornar a etiqueta transparente.

- Configure um atributo personalizado para rastrear que este rótulo é da equipe verde. Esta etapa é muito importante para os scripts na etapa 7.
- Na janela Propriedades, navegue até a seção Atributos e clique no ícone de mais. Um diálogo pop-up é exibido.
- No campo Name, insira teamColor.
- No menu suspenso Type, selecione BrickColor.
- Clique no botão Save.
- Defina o novo atributo teamColor como Mint.
- Insira um UIAspectRatioConstraint em TeamAIcon para garantir que a proporção da etiqueta e de seus elementos de UI filhos permaneça a mesma, independentemente do tamanho da tela do jogador.
- Crie o ícone.
- Insira um ImageLabel dentro de TeamAIcon.
- Selecione a nova etiqueta e, na janela Propriedades,
- Defina Image como rbxassetid://14309678670 para exibir o ícone da equipe verde.
- Defina AnchorPoint como 0.5, 0.5 para definir o ponto de origem da etiqueta no meio dela (50% da esquerda para a direita da etiqueta e 50% de cima para baixo da etiqueta).
- Defina BackgroundTransparency como 1 para tornar o fundo da etiqueta completamente transparente.
- Defina Name como Icon.
- Defina Position como {0.5, 0},{0.5, 0} para posicionar a etiqueta no meio de sua etiqueta pai.
- Defina Size como {0.7, 0},{0.6, 0} para encurtar a etiqueta.
- Defina ScaleType como Fit para que a imagem se ajuste dentro de seu contêiner e não se estique em vários tamanhos de tela.

Crie o ícone e a cor da equipe rosa.
- Duplicar TeamAIcon e seus filhos.
- Selecione o TeamAIcon duplicado e, na janela Propriedades,
- Defina BackgroundColor3 como 255, 170, 255 para definir a cor de fundo da etiqueta como rosa carnê.
- Defina Name como TeamBIcon.
- Defina o atributo teamColor como Carnation Pink.
- Selecione o filho Icon duplicado de TeamBIcon e, na janela Propriedades, defina Image como rbxassetid://14309678549 para exibir o ícone da equipe rosa.

Referencie os seguintes scripts ReplicatedStorage dentro do arquivo de lugar exemplo Laser Tag que exibem programaticamente o indicador do jogador com a cor e ícone de equipe apropriados enquanto um jogador está ativo em uma rodada.
O seguinte script requer um conjunto de scripts de módulo que trabalham juntos para configurar o principal Heads Up Display (HUD), incluindo startSyncingTeamColor, setPlayerName e setPlayerPortrait. Após um jogador entrar em uma rodada e selecionar seu blaster, este script garante que todos os elementos de UI do HUD sejam exibidos adequadamente para o estado, dispositivo e status da equipe do jogador.
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.LocalPlayerlocal gui = localPlayer.PlayerGui:WaitForChild("HUDGui")setPlayerPortrait(gui)setPlayerName(gui)startSyncingTeamColor(gui)setObjective(gui)startSyncingTeamPoints(gui)disableMouseWhileGuiEnabled(gui)setupHitmarker(gui)setupTouchButtonAsync(gui)
Tela de campo de força
Uma tela de campo de força é um elemento de UI que sobrepõe o viewport para informar os jogadores que estão seguros de disparos da equipe inimiga enquanto entram ou retornam a uma rodada. Seguindo as diretrizes estéticas para ícones de Escolher um Estilo de Arte, a experiência de laser tag de exemplo utiliza um padrão hexagonal semi-transparente para simbolizar um campo de força. Essa decisão de design não apenas reforça o estilo artístico futurista geral para toda a UI na experiência, mas também comunica o estado do jogador sem qualquer texto ou orientação adicional.

Para reproduzir exatamente a tela de campo de força na experiência de exemplo Laser Tag:
Insira um ImageLabel no objeto ForceFieldGui ScreenGui.
Na janela Explorer, navegue até o serviço StarterGui.
Passe o mouse sobre seu objeto filho ForceFieldGui e clique no ícone ⊕. Um menu contextual é exibido.
No menu contextual, insira um ImageLabel.

Selecione a nova etiqueta e, na janela Propriedades,
Defina Image como rbxassetid://14462567888.
Defina BackgroundTransparency como 0.8 para tornar o campo de força translúcido.
Defina Size como {1, 0},{1, 0} para que a imagem preencha toda a tela (100% horizontalmente e 100% verticalmente do objeto ScreenGui pai).
Defina ScaleType como Tile para que o hexágono se repita por toda a tela.
Defina TileSize como {0, 104},{0, 180}.

Insira um objeto UIGradient na etiqueta.
Selecione o novo objeto de gradiente e, na janela Propriedades,
Defina Color como uma sequência de cores que começa azul, se torna branca e depois volta a ficar azul.
Defina Color como 120, 192, 250 para aplicar um tom de azul claro a todos os hexágonos.
Clique na propriedade Color e depois clique no botão ⋯. Um pop-up de sequência de cores é exibido.

Cada triângulo no eixo inferior da sequência de cores é um ponto-chave que determina o valor de cor da propriedade naquele ponto da imagem da esquerda para a direita.
Clique e arraste na sequência de cores até atingir um valor de Time de 0.05, em seguida, clique no pequeno quadrado ao lado de Color para abrir a janela pop-up Colors.
Selecione um branco brilhante e feche a janela pop-up.
Clique e arraste na sequência de cores até atingir um valor de Time de 0.95, depois abra a janela pop-up Colors novamente e selecione a mesma cor branca de antes.

Defina Rotation como 225 para que a parte azul de sua sequência de cores apareça nos cantos superior esquerdo e inferior direito.

Defina Transparency como uma sequência numérica que faz com que o campo de força pareça estar brilhante.
Clique na propriedade Transparency e depois clique no botão ⋯. Um pop-up de sequência numérica é exibido. Cada quadrado no início e no final da sequência numérica é um ponto-chave que determina o valor de transparência da propriedade naquele ponto da imagem da esquerda para a direita.
Defina as seguintes propriedades de tempo e valor ao longo da sequência numérica:
- Time = 0, Value = 0.25
- Time = .101, Value = 0.875
- Time = .183, Value = 0
- Time = .3, Value = 1
- Time = .7, Value = 1
- Time = 1, Value = 0.9


Duplicar a ImageLabel da etapa 2.
Selecione o objeto UIGradient dentro da etiqueta duplicada e, na janela Propriedades,
Defina Rotation como -45 para virar a imagem, de modo que ela quase se espelhe ao longo do eixo Y.

Modifique Transparency para fazer o brilho parecer mais orgânico.
- Clique na propriedade Transparency e depois clique no botão ⋯. Um pop-up de sequência numérica é exibido.
- Selecione o terceiro quadro-chave e clique no botão Delete.

Referencie os seguintes scripts ReplicatedStorage dentro do arquivo de lugar exemplo Laser Tag que exibem programaticamente a tela de campo de força enquanto um jogador entra ou retorna a uma rodada.
O seguinte script cliente ReplicatedStorage.ForceFieldClientVisuals substitui a aparência padrão do ForceField por StarterGui.ForceFieldGui. Quando os jogadores entram em uma experiência e aparecem em um SpawnLocation com uma propriedade Duration maior que 0, o comportamento padrão em todas as experiências é fornecer a seus avatares um orbe azul protetor que momentaneamente os impede de perder saúde.
Este script começa ouvindo quando o ForceField é adicionado a um personagem, desabilita os visuais padrão da força de campo em primeira pessoa e, em seguida, habilita o objeto ScreenGui ForceFieldGui. Observe que isso não impacta os visuais em terceira pessoa quando os jogadores olham para outros jogadores reaparecendo na experiência.


local Players = game:GetService("Players")
local localPlayer = Players.LocalPlayer
local function onCharacterAddedAsync(character: Model)
local forceField = character:WaitForChild("ForceField", 3)
if not forceField then
-- Se o jogador aparecer em um ponto de spawn com a força de campo desabilitada
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)
Tela de reaparecimento
Uma tela de reaparecimento é um elemento de IU que escurece a viewport para informar os jogadores que eles foram eliminados e que o servidor está no processo de reenviá-los de volta à sua zona de spawn. Este elemento de IU é importante porque dá aos jogadores tempo para processar que foram eliminados e traçar sua próxima jogada antes de se juntarem à rodada ativa.
Para mais informações sobre comportamento de reaparecimento personalizado na experiência de exemplo de laser tag, veja Respawn Characters do currículo de Scripting de Gameplay.

Para recriar exatamente a tela de reaparecimento dentro da experiência de exemplo Laser Tag:
Crie o banner de informações central.
Insira um ImageLabel no objeto OutStateGui ScreenGui.
Na janela Explorer, navegue até o serviço StarterGui.
Passe o mouse sobre seu objeto filho OutStateGui, em seguida, clique no ícone ⊕. Um menu contextual aparece.
No menu contextual, insira um ImageLabel.

Selecione o novo rótulo, em seguida, na janela Properties,
Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do novo botão no meio dele (50% da esquerda para a direita do rótulo, e 50% do topo para a parte inferior do rótulo).
Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
Defina Position para {0.5, 0},{0.5, 0} para colocar o rótulo no meio de seu contêiner (50% da esquerda para a direita do ScreenGui pai, e 50% do topo para a parte inferior do ScreenGui pai).
Defina Size para {0.48, 0},{0.06, 0} para alargar o rótulo (48% horizontalmente e 6% verticalmente do ScreenGui pai).
Defina Name para Block.
Defina Image para rbxassetid://14304827265 para tornar a imagem um trapézio.
Defina ImageColor para 0,0,0 para tornar o trapézio preto.
Defina ImageTransparency para 0.3 para reduzir a opacidade do rótulo em 30%, e combinar com todos os elementos de IU pretos na experiência.

Insira um UIAspectRatioConstraint em Block para garantir que a proporção do rótulo e seus elementos de IU filhos permaneçam os mesmos, não importa o tamanho da tela do jogador.
Selecione a nova restrição, em seguida, na janela Properties, defina AspectRatio para 13.78.
Insira um TextLabel em Block para o texto informativo.
Selecione o novo rótulo, em seguida, na janela Properties,
Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do rótulo no meio dele (50% da esquerda para a direita do rótulo, e 50% do topo para a parte inferior do rótulo).
Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
Defina Position para {0.5, 0},{0.5, 0} para colocar o rótulo no meio de seu rótulo pai (50% da esquerda para a direita do rótulo pai, e 50% do topo para a parte inferior do rótulo pai).
Defina Size para {.85, 0},{0.55, 0} para que o texto ocupe a maior parte da área do trapézio (85% horizontalmente e 55% verticalmente do rótulo pai).
Defina Name para BodyTextLabel.
Defina FontFace para Montserrat para se adequar à estética futurista.
Defina Weight para Bold para engrossar a fonte.
Defina Text para Respawnando….
Defina TextColor3 para 255, 255, 255 para tornar o texto branco.
Ative TextScaled.

Crie o cabeçalho.
Insira um ImageLabel em Block.
Selecione o novo rótulo, em seguida, na janela Properties,
Defina AnchorPoint para 0.5, 1 para definir o ponto de origem do rótulo no meio da parte inferior dele (50% da esquerda para a direita do rótulo, e 100% do topo para a base do rótulo).
Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
Defina Position para {0.5, 0},{0, 0} para colocar o rótulo na parte superior do meio de seu rótulo pai (50% da esquerda para a direita do rótulo pai, e 0% do topo para a parte inferior do rótulo pai).
Defina Size para {0.46, 0},{0.56, 0} para alargar o rótulo (46% horizontalmente e 56% verticalmente do rótulo pai).
Defina Name para Header.
Defina Image para rbxassetid://14304826985 para fazer a imagem um desvanecimento multidirecional.
Defina ImageColor para 245, 46, 46 para fazer o desvanecimento vermelho, para indicar que o jogador está temporariamente inativo enquanto está eliminado da rodada.

Insira um TextLabel em Header para o texto informativo.
Selecione o novo rótulo, em seguida, na janela Properties,
Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do rótulo no meio dele (50% da esquerda para a direita do rótulo, e 50% do topo para a parte inferior do rótulo).
Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
Defina Position para {0.5, 0},{0.5, 0} para colocar o rótulo no meio de seu rótulo pai (50% da esquerda para a direita do rótulo pai, e 50% do topo para a parte inferior do rótulo pai).
Defina Size para {.85, 0},{0.55, 0} para que o texto ocupe a maior parte da área do desvanecimento (85% horizontalmente e 55% verticalmente do rótulo pai).
Defina Name para HeaderTextLabel.
Defina FontFace para Montserrat para se adequar à estética futurista.
Defina Weight para Black para engrossar a fonte.
Defina Text para ELIMINADO - VOCÊ ESTÁ FORA!
Defina TextColor3 para 255, 255, 255 para tornar o texto branco.
Ative TextScaled.

Crie o desvanecimento nas bordas da tela.
- Insira um ImageLabel em OutStateGui.
- Selecione o novo rótulo, em seguida, na janela Properties,
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do rótulo no meio dele (50% da esquerda para a direita do rótulo, e 50% do topo para a parte inferior do rótulo).
- Defina BackgroundColor3 para 0,0,0 para definir a cor de fundo do rótulo como preto.
- Defina BackgroundTransparency para 0.5 para tornar o fundo do rótulo parcialmente transparente.
- Defina Position para {0.5, 0},{0.5, 0} para colocar o rótulo no meio de seu contêiner (50% da esquerda para a direita do ScreenGui pai, e 50% do topo para a parte inferior do ScreenGui pai).
- Defina Size para {1, 0},{1, 0} para alargar o rótulo para a tela inteira (100% horizontalmente e 100% verticalmente do ScreenGui pai).
- Defina ZIndex para -1 para exibir o desvanecimento atrás de outros elementos de IU.
- Defina Name para Header.
- Defina Image para rbxassetid://14309518613 para fazer a imagem um desvanecimento nas bordas.
- Defina ImageTransparency para 0.1 para tornar o desvanecimento ligeiramente translúcido.
Referencie o seguinte script ReplicatedStorage dentro do arquivo de lugar de exemplo Laser Tag que exibe programaticamente a tela de reaparecimento quando a saúde de um jogador chega a zero e eles estão no processo de reaparecer de volta na zona de spawn da equipe.
O seguinte script cliente ReplicatedStorage.PlayerStateHandler contém funções que acionam diferentes tipos de comportamento de acordo com o atributo playerState. Todas as respostas a eventos estão logicamente agrupadas neste script porque exigem um comportamento similar de habilitar ou desabilitar os controles dos jogadores, movimento da câmera e qual camada de IU está visível.
Quando a saúde de um jogador chega a zero, seu playerState se torna TaggedOut, o que aciona a função onTaggedOut(). onTaggedOut() aciona imediatamente o seguinte comportamento:
- O jogador não pode se mover na arena.
- O jogador não pode mover sua câmera.
- O jogador não pode usar sua blaster.
- O StarterGui.OutStateGui torna-se exclusivamente habilitado.
Quando o jogador reaparece, seu playerState se torna SelectingBlaster, o que aciona a função onSelectingBlaster(). onSelectingBlaster() em seguida, habilita exclusivamente o StarterGui.PickABlasterGui, que desativa automaticamente a tela de reaparecimento. Para mais informações sobre essas condições, veja Handle Client State do currículo de Scripting de Gameplay.
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"),
}
-- Desabilita todas as camadas de IU, exceto a exceção dada
local function setGuiExclusivelyEnabled(enabledGui: ScreenGui?)
-- guiLayers contém uma lista das guis que devem ser configuradas exclusivamente.
for _, screenGui in guiLayers do
screenGui.Enabled = screenGui == enabledGui
end
end
local function onSelectingBlaster()
-- Habilita a câmera para que os jogadores possam olhar ao redor enquanto selecionam uma blaster
togglePlayerCamera(true)
togglePlayerMovement(false)
setGuiExclusivelyEnabled(playerGui.PickABlasterGui)
-- Desabilita a blaster enquanto seleciona uma blaster
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onPlaying()
-- Habilita o movimento do jogador após escolher uma blaster
togglePlayerMovement(true)
setGuiExclusivelyEnabled(playerGui.HUDGui)
-- Habilita a blaster enquanto joga
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Ready)
-- Programa a lógica de destruição da força de campo quando o jogador começa a jogar
scheduleDestroyForceField()
end
local function onTaggedOut()
-- Desabilita controles enquanto está marcado
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- Desabilita a blaster enquanto está marcado
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onInLobby()
-- Habilita controles enquanto está no lobby
togglePlayerMovement(true)
togglePlayerCamera(true)
-- Oculta todo o HUD enquanto está no lobby
setGuiExclusivelyEnabled(nil)
-- Desabilita a blaster enquanto está no lobby
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
-- Lida com o estado inicial do jogador se estiver definido
local initialPlayerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
onPlayerStateChanged(initialPlayerState)
local function updateFromPlayerState()
onPlayerStateChanged(localPlayer:GetAttribute(PlayerAttribute.playerState))
end
-- Lida com futuras atualizações de estado do jogador
localPlayer:GetAttributeChangedSignal(PlayerAttribute.playerState):Connect(updateFromPlayerState)
-- Certifique-se de que as mudanças ainda sejam aplicadas após o reaparecimento
localPlayer.CharacterAdded:Connect(updateFromPlayerState)
Criar objetos SurfaceGui
Para exibir IU na superfície de uma parte no espaço 3D que responde à lógica de scripting para cada jogador individual, você pode adicionar um objeto SurfaceGui à parte que deseja exibir sua IU dentro do serviço ReplicatedStorage. Essa técnica garante que sua IU e sua lógica de scripting estejam disponíveis tanto para o servidor quanto para o cliente de cada jogador.
Os objetos SurfaceGui contêm todos os GuiObjects que exibem na superfície de uma parte no espaço 3D. A experiência de laser tag de exemplo inclui apenas uma instância de um objeto SurfaceGui: o medidor de cooldown que é exibido sobre a blaster de cada jogador. Este objeto precisa de lógica de scripting para cada jogador, pois responde ativamente à entrada de cada jogador individual e fornece feedback visual sobre quando eles podem disparar sua blaster novamente.
Para criar um objeto SurfaceGui:
- Na janela Explorer, passe o mouse sobre o serviço ReplicatedStorage, em seguida, clique no ícone ⊕. Um menu contextual aparece.
- No menu contextual, insira um objeto Part.
- Insira um objeto ScreenGui dentro da parte.
- Renomeie o SurfaceGui de acordo com o contexto de seus elementos de IU filhos.
- Repita este processo para cada elemento de IU que você precisa exibir na superfície de uma parte no espaço 3D.

Medidor de cooldown
Um medidor de cooldown é um componente de IU que informa os jogadores quanto tempo eles precisam esperar antes de poder disparar sua blaster novamente. Essa ligeira pausa impede que os jogadores consigam disparar tão rapidamente quanto conseguem clicar ou pressionar um botão, o que não é realista para a jogabilidade de laser tag.
Para recriar exatamente o medidor de cooldown dentro da experiência de exemplo Laser Tag:
Crie uma parte para segurar seu objeto SurfaceGui.
- Na janela Explorer, passe o mouse sobre o Workspace, em seguida, clique no ícone ⊕. Um menu contextual aparece.
- No menu contextual, insira uma parte block. Este é um local temporário para a parte para que você possa visualizar as mudanças em cada etapa do processo.
Posicione e oriente a parte ao redor do local onde o personagem de um jogador seguraria sua blaster, em seguida, na janela Properties,
Defina Transparency para 1 para tornar a parte completamente transparente.
Defina Name para CooldownBarPrefab.
Defina Size para 0.169, 0.027, 2.537 para escalar a parte para um tamanho aproximadamente igual ao comprimento da blaster.
Desative CanCollide e CanQuery.

Insira um SurfaceGui em CooldownBarPrefab.
Selecione o novo SurfaceGui, em seguida, na janela Properties,
Defina Face para Top para que a IU seja exibida voltada para cima.
Defina LightInfluence e MaxDistance para 0.
Defina PixelsPerStud para 200.

Crie a barra preta.
Insira um ImageLabel no SurfaceGui.
Selecione o novo rótulo, em seguida, na janela Properties,
- Remova o valor padrão de Image.
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do rótulo no meio dele (50% da esquerda para a direita do rótulo, e 50% do topo para a parte inferior do rótulo).
- Defina BackgroundColor3 para 0,0,0 para definir a cor de fundo do rótulo como preto.
- Defina BackgroundTransparency para 0.4 para tornar o fundo do rótulo semi-transparente.
- Defina Position para {0.5, 0},{0.5, 0} para colocar o rótulo no meio de seu contêiner (50% da esquerda para a direita do SurfaceGui pai, e 50% do topo para a parte inferior do SurfaceGui pai).
- Defina Size para {1, 0},{1, 0} para alargar o rótulo para toda a parte (100% horizontalmente e 100% verticalmente do SurfaceGui pai).
- Defina Name para Container.

Arredonde os cantos do contêiner.
Insira um objeto UICorner em Container.
Selecione o UICorner, em seguida, na janela Properties, defina CornerRadius para 0.15, 0 para arredondar ligeiramente os cantos.

Crie a barra vermelha.
- Insira um ImageLabel em Container.
- Selecione o novo rótulo, em seguida, na janela Properties,
- Remova o valor padrão de Image.
- Defina AnchorPoint para 1, 0.5 para definir o ponto de origem do rótulo no meio da parte direita dele (100% da esquerda para a direita do rótulo, e 50% do topo para a parte inferior do rótulo).
- Defina BackgroundColor3 para 172, 13, 13 para definir a cor de fundo do rótulo como um vermelho escuro.
- Defina BackgroundTransparency para 0.2 para tornar o fundo do rótulo levemente transparente.
- Defina Name para Bar.
- Defina Position para {1, 0},{0.5, 0} para colocar o rótulo no meio da parte direita de seu contêiner (100% da esquerda para a direita do rótulo pai, e 50% do topo para a parte inferior do rótulo pai).
- Defina Size para {0, 0},{1, 0} para alongar o rótulo até o topo do rótulo pai (0% horizontalmente e 100% verticalmente do rótulo pai). Esta etapa também é benéfica para o comportamento de tweening que ocorre nos scripts na etapa 8.
Arredonde os cantos do rótulo.
- Insira um objeto UICorner em Bar.
- Selecione o UICorner, em seguida, na janela Properties defina CornerRadius para 0.15, 0 para arredondar ligeiramente os cantos.
Mova CooldownBarPrefab para ReplicatedStorage.
Crie uma estrutura de pastas para organizar seus objetos de IU. O exemplo usa uma pasta Instances com uma subpasta Guis.

Mova CooldownBarPrefab para Guis.
Referencie os seguintes scripts ReplicatedStorage dentro do arquivo de lugar de exemplo Laser Tag que programaticamente conectam o medidor de cooldown à blaster do jogador e, em seguida, anima a barra vermelha depois que um jogador dispara sua blaster.
O seguinte script cliente ReplicatedStorage.FirstPersonBlasterVisuals lida com toda a lógica visual para a blaster em primeira pessoa do jogador. Ele requer um conjunto de scripts de módulo que trabalham juntos para configurar visuais de blaster que se sentem mais realistas para a jogabilidade de laser tag, incluindo FirstPersonBlasterVisuals.addCooldownBar e FirstPersonBlasterVisuals.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()
-- Adiciona o rig em primeira pessoa
rigModel = blasterConfig.RigModel:Clone()
rigModel.Parent = Workspace
-- Adiciona a cooldownBar
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
-- Isso também destrói a barra de cooldown, uma vez que está associada ao rig
rigModel:Destroy()
rigModel = nil
end
end
-- Executa efeitos visuais em primeira pessoa quando um disparo ocorre
laserBlastedBindableEvent.Event:Connect(function(blastData: BlastData.Type)
runBlastVisuals(rigModel.PrimaryPart.TipAttachment, blastData, animations.blastAnimation)
runCooldownBarEffect(cooldownBar)
end)
-- Vincula o rig à câmera se existir
RunService.RenderStepped:Connect(function()
if rigModel then
-- Atualiza a CFrame do rig em relação à posição da câmera e RIG_OFFSET_FROM_CAMERA
rigModel:PivotTo(currentCamera.CFrame * RIG_OFFSET_FROM_CAMERA)
end
end)
-- Lida com alterações visuais quando o tipo de blaster muda durante o jogo
localPlayer:GetAttributeChangedSignal(PlayerAttribute.blasterType):Connect(function()
local playerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
if playerState == PlayerState.Playing then
removeFirstPersonVisuals()
addFirstPersonVisuals()
end
end)
-- Lida com alterações visuais quando o playerState muda
localPlayer:GetAttributeChangedSignal(PlayerAttribute.playerState):Connect(function()
local newPlayerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
-- Remove os visuais quando o jogador está selecionando uma blaster ou está no lobby
if newPlayerState == PlayerState.SelectingBlaster or newPlayerState == PlayerState.InLobby then
removeFirstPersonVisuals()
-- Adiciona os visuais novamente quando o jogador termina de selecionar a blaster.
elseif newPlayerState == PlayerState.Playing then
addFirstPersonVisuals()
end
end)
Criar objetos BillboardGui
Para exibir elementos de IU dentro do espaço 3D que respondem à lógica de scripting e sempre enfrentam a câmera de cada jogador, independentemente do ângulo de visualização deles, como nomes de jogadores ou marcadores de mapa, você pode criar um objeto BillboardGui como filho de um BasePart ou Attachment que exista no espaço 3D.
A experiência de laser tag de exemplo inclui dois objetos BillboardGui separados dentro do serviço ReplicatedStorage:
- OtherPlayerIndicatorGuiPrefab - Exibe um círculo rosa ou verde acima da cabeça de cada jogador quando estão ativos em uma rodada.
- TaggedOutIndicatorGuiPrefab - Exibe acima da cabeça de um jogador quando eles estão eliminados da rodada.
Depois de criar um objeto BillboardGui, você pode criar e personalizar seus filhos GuiObjects de acordo com o propósito de cada contêiner. Para demonstrar, nas seções imediatas a seguir, você aprenderá como implementar elementos de IU para ambos os tipos de indicadores dentro da experiência de exemplo de laser tag. Você pode ajustar qualquer parte do processo para atender às especificações de sua própria experiência.
Para criar um objeto BillboardGui:
- Na janela Explorer, passe o mouse sobre um BasePart ou Attachment, em seguida, clique no ícone ⊕. Um menu contextual aparece.
- No menu contextual, insira um objeto BillboardGui.
- Renomeie o BillboardGui de acordo com o contexto de seus elementos de IU filhos.
- Repita este processo para cada elemento de IU que você precisa exibir contextualizado acima das cabeças dos jogadores.
Indicador de equipe
Um indicador de equipe é um elemento de IU que informa os jogadores a qual equipe outros jogadores na rodada pertencem, para que possam facilmente diferenciar entre seus aliados e inimigos. Esta informação é importante, pois a jogabilidade de uma experiência de atirador em primeira pessoa exige que os jogadores tomem decisões estratégicas rápidas enquanto estão em zonas de combate, para que não sejam eliminados e percam a partida.

Para recriar exatamente o indicador de equipe dentro da experiência de exemplo Laser Tag:
Insira um objeto BillboardGui em um rig temporário.
A partir da barra de ferramentas Home ou Avatar, clique em Character.
Selecione entre as opções disponíveis. O exemplo usa um tipo de rig R15, uma forma de corpo feminina e um avatar Rthro. O rig é exibido tanto no viewport 3D quanto na janela Explorer sob o nome Rig.
Na janela Explorer, navegue até a malha Head do rig, em seguida, clique no ícone ⊕. Um menu contextual aparece.
No menu contextual, insira um BillboardGui.

Selecione o novo BillboardGui, em seguida, na janela Properties,
Defina LightInfluence para 0 para evitar que a luz ambiental afete a cor do indicador.
Defina Name para OtherPlayerIndicatorPrefab.
Defina Size para {0, 10},{0, 10} para tornar o rótulo significativamente menor.
Defina StudsOffsetWorldSpace para 0, 4, 0 para posicioná-lo acima da cabeça do rig.

Insira um objeto Frame no OtherPlayerIndicatorPrefab.
Selecione o novo quadro, em seguida, na janela Properties,
Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do quadro no meio dele (50% da esquerda para a direita do rótulo, e 50% do topo para a parte inferior do rótulo).
Defina BackgroundColor3 para 255, 3, 0 para definir a cor de fundo do quadro como vermelho como uma cor de espaço reservado.
Defina Position para {0.5, 0},{0.5, 0} para colocar o quadro no meio de seu contêiner (50% da esquerda para a direita do BillboardGui pai, e 50% do topo para a parte inferior do BillboardGui pai).
Defina Size para {1, -2},{1, -2} para encurtar o quadro à área de superfície do BillboardGui.

Insira um objeto UICorner em Frame para arredondar completamente os cantos.

Insira um objeto UIStroke em Frame para contornar o círculo do indicador.

Mova OtherPlayerIndicatorPrefab para ReplicatedStorage.
Referencie o seguinte script ReplicatedStorage dentro do arquivo de lugar de exemplo Laser Tag 1A que exibe programaticamente o indicador de equipe para cada jogador em uma rodada ativa, a menos que eles estejam na equipe inimiga e ocultos.
O seguinte script ReplicatedStorage.OtherPlayerIndicatorGuiSetup é executado quando os jogadores aparecem na arena para uma rodada ativa. Ele anexa o indicador de equipe chamando a função addIndicatorToCharacter(), que localiza o objeto Head de cada personagem jogador participando da rodada. Se eles ainda não tiverem um indicador de equipe, o script então clona e adiciona a IU otherPlayerIndicatorPrefab à Head do personagem e define a cor do indicador de equipe para a cor de sua equipe.
Se outros jogadores estiverem na mesma equipe, o indicador de equipe sempre será exibido, mesmo se estiverem atrás de objetos no espaço 3D; se outros jogadores estiverem na equipe inimiga, o indicador de equipe só será exibido se não houver um objeto no espaço 3D para ocultá-los.
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
-- Apenas adiciona indicadores a jogadores participando da rodada
if not otherPlayer.Team then
return
end
-- Evita adicionar indicadores duplicados, criando um novo apenas se não existir
local gui = otherHead:FindFirstChild(otherPlayerIndicatorPrefab.Name)
if not gui then
gui = otherPlayerIndicatorPrefab:Clone()
gui.Frame.BackgroundColor3 = otherPlayer.TeamColor.Color
gui.Parent = otherHead
end
-- O indicador está sempre por cima, apenas se o jogador for amigo
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()
Indicador de eliminado
Um indicador de eliminado é um elemento de IU que informa os jogadores quando outros jogadores não estão mais ativos na rodada e estão em processo de reaparecimento de volta à sua zona de spawn. Esta informação é importante porque a jogabilidade de uma experiência de tiro em primeira pessoa exige que os jogadores se movam rapidamente para seu próximo alvo assim que eliminam um jogador, para que não fiquem vulneráveis na arena ao jogar no mesmo local por muito tempo.

Para recriar exatamente o indicador de eliminado dentro da experiência de exemplo Laser Tag:
Insira um objeto BillboardGui em um rig temporário para que você possa visualizar as mudanças em cada etapa do processo.
A partir da barra de ferramentas Home ou Avatar, clique em Character.
Selecione entre as opções disponíveis. O exemplo usa um tipo de rig R15, uma forma de corpo masculina e um avatar Rthro. O rig é exibido tanto no viewport 3D quanto na janela Explorer sob o nome Rig.
Na janela Explorer, navegue até a malha Head do rig, em seguida, clique no ícone ⊕. Um menu contextual aparece.
No menu contextual, insira um BillboardGui.

Selecione o novo BillboardGui, em seguida, na janela Properties,
Defina LightInfluence para 0 para evitar que a luz ambiental afete a cor do indicador.
Defina Name para TaggedOutIndicatorGuiPrefab.
Defina Size para {3, 0},{0.5, 0} para alargar o espaço para um rótulo.
Defina StudsOffset para 0, 3.25, 0 para posicioná-lo acima da cabeça de um jogador.

Insira um objeto ImageLabel dentro do TaggedOutIndicatorGuiPrefab.
Selecione o novo rótulo, em seguida, na janela Properties,
- Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do rótulo no meio dele (50% da esquerda para a direita do rótulo, e 50% do topo para a parte inferior do rótulo).
- Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
- Defina Name para Frame.
- Defina Position para {0.5, 0},{0.5, 0} para colocar o rótulo no meio de seu contêiner (50% da esquerda para a direita do BillboardGui pai, e 50% do topo para a parte inferior do BillboardGui pai).
- Defina Size para {1, 0},{1, 0} para alargar o rótulo por todo o BillboardGui (100% horizontalmente e 100% verticalmente do BillboardGui pai).
- Defina Image para rbxassetid://14304826985 para tornar a imagem um desvanecimento multidirecional.
- Defina ImageColor para 245, 46, 46 para tingir o rótulo de vermelho.

Insira um objeto TextLabel dentro do Frame.
Selecione o novo rótulo, em seguida, na janela Properties,
Defina AnchorPoint para 0.5, 0.5 para definir o ponto de origem do rótulo no meio dele (50% da esquerda para a direita do rótulo, e 50% do topo para a parte inferior do rótulo).
Defina BackgroundTransparency para 1 para tornar o fundo do rótulo completamente transparente.
Defina Name para BodyTextLabel.
Defina Position para {0.5, 0},{0.5, 0} para colocar o rótulo no meio de seu contêiner (50% da esquerda para a direita do rótulo pai, e 50% do topo para a parte inferior do rótulo pai).
Defina Size para {0.85, 0},{0.7, 0} para que o texto ocupe a maior parte da área de desvanecimento (85% horizontalmente e 70% verticalmente da imagem do rótulo pai).
Defina FontFace para Montserrat para se adequar à estética futurista.
Defina Weight para Bold para engrossar a fonte.
Defina Text para ELIMINADO.
Defina TextColor3 para 255, 255, 255 para tornar o texto branco.
Ative TextScaled.

Mova TaggedOutIndicatorGuiPrefab para ReplicatedStorage.
Referencie os seguintes scripts ServerScriptService dentro do arquivo Laser Tag 1A que exibem programaticamente o indicador de eliminado enquanto um jogador está reaparecendo de volta à zona de spawn de sua equipe.
O seguinte script de servidor ServerScriptService.SetupHumanoid é executado assim que um jogador carrega a experiência. Ele garante que sempre que o personagem de um jogador é adicionado ao modelo de dados, setupHumanoidAsync é chamado com seu 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)
-- Chama onCharacterAdded se o jogador já tem um personagem
if player.Character then
onCharacterAdded(player, player.Character)
end
-- Chama onCharacterAdded para todos os futuros spawns de personagens para este jogador
player.CharacterAdded:Connect(function(character: Model)
onCharacterAdded(player, character)
end)
end
-- Chama onPlayerAdded para quaisquer jogadores já no jogo
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end
-- Chama onPlayerAdded para todos os futuros jogadores
Players.PlayerAdded:Connect(onPlayerAdded)
Parabéns por completar o Currículo de Design de Interface do Usuário! Agora que você tem experiência em criar um estilo artístico, esboçar seus layouts e implementar seus designs no Studio do início ao fim, você pode expandir seu projeto com novas IU e funcionalidades, ou seguir currículos de tutoriais adicionais, como o Gameplay Scripting Curriculum que ensina sobre a organização geral e detalhes de implementação chave da experiência de exemplo de laser tag. Boa criação!