Marcadores de objetivos são usados em muitos jogos para guiar um jogador até a próxima meta ou ponto de interesse. Neste tutorial, você aprenderá a criar um marcador de objetivo reutilizável com o dispositivo Indicador de Mapa e Verse.
Funcionalidades da linguagem Verse usadas
struct: você pode agrupar variáveis de diferentes tipos em uma struct.
Método de extensão: um tipo especial de função que age como um membro de uma classe ou um tipo existente, mas não exige a criação de um novo tipo ou subclasse. Neste guia, você criará um método de extensão para struct.
argumento nomeado: um argumento que é passado para uma chamada de função com seu nome de parâmetro especificado.
APIs Verse usadas
creative_prop API: a API
creative_propfornece métodos para movimentação de adereços.Propriedades editáveis: várias propriedades são usadas tanto para referenciar dispositivos quanto para atualizar valores de variáveis para testes rápidos.
Instruções
Siga estas etapas para aprender a configurar um único dispositivo marcador de objetivo que possa se mover para vários objetivos ou pontos de interesse. Os scripts completos estão incluídos no final deste guia para servir de referência.
Como configurar o nível
Este exemplo usa os seguintes adereços e dispositivos:
1 Adereço de construção: um adereço que será usado para mover o dispositivo Indicador de Mapa.
1 dispositivo Indicador de Mapa: um dispositivo que exibe marcadores personalizados no minimapa e no mapa geral.
1 dispositivo Plataforma de Surgimento de Jogador: adicione esse dispositivo perto do adereço para que o jogador surja perto dele.
Como usar a API de adereço
A primeira etapa para mover um dispositivo com o Verse é mover um adereço com a API de adereço. Siga estas etapas para mover um adereço pelo seu nível.
Crie um novo dispositivo Verse chamado objective_coordinator_device.
Sob as expressões
usingpadrão na parte superior do arquivo Verse, adicione uma expressãousingpara o módulo SpatialMath. Este módulo contém o código ao qual você fará referência para mover adereços.Verseusing { /UnrealEngine.com/Temporary/SpatialMath }Adicione duas propriedades editáveis:
Uma constante
creative_propchamadaRootProppara armazenar uma referência ao adereço móvel.Uma constante
transformchamadaDestinationpara armazenar o local até onde o adereço será movido.Verseobjective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} @editable Destination<public> : transform = transform{}
Se você executar esse código e arrastar seu objective_coordinator_device até seu nível, verá as duas propriedades no painel Detalhes.
O método
TeleportTo[]é o que realmente move o adereço. Chame-o dentro de uma expressão if e use colchetes em vez de parênteses, poisTeleportTo[]é uma expressão falível. A expressãoifcria um contexto de falha.Verseif(RootProp.TeleportTo[Destination.Translation, Destination.Rotation]): Print("Prop move successful") else: Print("Prop move failed")Os argumentos para
TeleportTo[]são Translation e Rotation. Ambos vêm da sua propriedade Destination.Novamente no editor, arraste um adereço de Fortnite > Galerias > Adereços no Navegador de Conteúdo. O adereço usado neste guia se chama Coastal Buoy 02B, mas qualquer item da pasta Props deve funcionar.
Selecione seu dispositivo Coordenador de Objetivos no Outliner. No painel Detalhes, defina o RootProp para seu adereço. Neste exemplo, RootProp está definido como Coastal Buoy 02B.
No painel Detalhes, expanda o Destino. Como o Destino é do tipo
transform, é composto de Escala, Rotação e Translação. Para mover o adereço, você só precisa alterar Translação, então expanda essa opção. Defina o campo que termina com X como 5.000,0Ao testar o código, é uma boa ideia fazer grandes alterações nos valores para que os efeitos sejam óbvios. Pequenas alterações podem tornar difícil saber se seu código está fazendo o que você espera.
Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /UnrealEngine.com/Temporary/SpatialMath } objective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} # Where the marker will be moved toClique em Verse, em Compilar código Verse e, em seguida, clique em Iniciar sessão. Por fim, clique em Começar jogo. Você deve ver seu adereço se mover.
Pai e structs
Agora você tem um adereço se movendo no seu nível, mas o objetivo real é mover um dispositivo Indicador de Mapa para que os jogadores possam usá-lo como trajetória. Siga estas etapas para adicionar um Adereço de construção e um dispositivo Indicador de Mapa ao seu nível e conectá-lo ao Adereço de construção.
Clique com o botão direito do mouse no Navegador de Conteúdo para abrir o menu de contexto.
Selecione a Classe de Blueprint no menu de contexto.
Na janela Escolha a classe-pai, clique em Adereço de construção.
Uma nova Classe de Blueprint aparecerá no seu Navegador de Conteúdo. Renomeie-a como BuildingProp.
Arraste o Adereço de construção até seu nível. Esse adereço não tem malha, então você só verá seu dispositivo de transformação.
No Organizador, arraste o dispositivo Indicador de Mapa até o Adereço de construção. Essa ação transforma o Adereço de construção no pai do dispositivo Indicador de Mapa. Agora, quando o Adereço de construção se move, o dispositivo Indicador de Mapa se move com ele.
Você já sabe criar um dispositivo usando Verse, mas também pode criar arquivos Verse que não têm seus próprios dispositivos.
Crie um novo arquivo Verse e chame-o de objective_marker. Esse arquivo não criará um dispositivo. Em vez disso, ele conterá a definição de um
structa ser exposta ao dispositivo Verse que você criou anteriormente.Comece declarando um
structdenominado objective_marker. Ele terá dois membros:RootPropeMapIndicator. Ambos devem ter o especificador@editable.Verseobjective_marker<public> := struct<concrete>: @editable RootProp<public> : creative_prop = creative_prop{} @editable MapIndicator<public> : map_indicator_device = map_indicator_device{}
Métodos de extensão e argumentos nomeados
Declare um único método, MoveMarker, que moverá o membro RootProp e seu dispositivo Indicador de Mapa anexado. Esse método apresenta duas funcionalidades de linguagem: métodos de extensão e argumentos nomeados.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =Métodos de extensão: você está adicionando o método
MoveMarker()ao structobjective_marker. Um método de extensão é declarado usando parênteses ao redor de um identificador e tipo, separados por um caractere de dois-pontos. Neste caso:(Marker : objective_marker).Argumentos nomeados: o segundo argumento
?OverTimeusa?para indicar que ele deve ser nomeado na chamada da funçãoMoveMarker. Isso ajuda qualquer desenvolvedor que esteja lendo ou programando uma chamada paraMoveMarkera entender o que o argumentofloatestá fazendo.
MoveMarker() chamará um dos dois métodos da API de adereço: TeleportTo[], que você usou anteriormente, ou MoveTo(). Crie um bloco if..else para testar se o parâmetro OverTime é maior que 0,0. Se for, chame MoveTo(). Isso fará com que seu objetivo se mova para o próximo local durante o período especificado, em vez de se teletransportar instantaneamente.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =
if (OverTime > 0.0):
Marker.RootProp.MoveTo(Transform.Translation, Transform.Rotation, OverTime)
else:
if:
Marker.RootProp.TeleportTo[Transform.Translation, Transform.Rotation]Se compilar o código agora, ele será bem-sucedido, mas você não verá um novo dispositivo na pasta CreativeDevices do Navegador de Conteúdo. Isso ocorre porque objective_marker é um struct, e não uma classe que herda de creative_device.
Como atualizar o dispositivo Coordenador de Objetivos
Agora que você tem um novo tipo para referenciar, precisa atualizar o objective_coordinator_device para referenciá-lo.
Exclua a propriedade
RootPrope substitua-a por uma propriedade chamadaPickupMarkerdo tipoobjective_marker. Esse é o tipo que você criou.MoveMarker()requer um argumento do tipofloat, então crie-o como uma propriedade editável chamadaMoveTime.Exclua a chamada para
TeleportTo[]. Em vez dessa chamada, chame o métodoMoveMarker()que você criou paraobjective_marker. Isso requer o argumento com o nome?OverTime.Verseobjective_coordinator_device<public> := class<concrete>(creative_device): @editable PickupMarker<public> : objective_marker = objective_marker{} # Where the marker will be moved to @editable Destination<public> : transform = transform{} # How much time the marker should take to reach its new location
Compile esse código e verifique os detalhes do dispositivo coordenador de objetivos. Você deve ver as propriedades PickupMarker e MoveTime, e PickupMarker deve conter RootProp e MapIndicator.
Defina o campo RootProp como BuildingProp e o campo MapIndicator como dispositivo Indicador de Mapa
Compile seu código e clique em Iniciar sessão. Você verá um marcador no seu minimapa que se move logo após o início do jogo. Teste-o com
MoveTimedefinido com valores diferentes, incluindo0,0. Pense em qual movimento seria mais adequado para diferentes cenários.
GetPlayers() e ActivateObjectivePulse()
Existe uma maneira de dar aos seus jogadores uma ajuda extra para alcançar o próximo objetivo. Ela se chama pulso de objetivo e, quando ativa, mostra uma linha pontilhada que se move do jogador em direção ao dispositivo Indicador de Mapa. Siga as instruções abaixo para adicionar um pulso de objetivo ao seu dispositivo coordenador de objetivos.
O método necessário para ativar o pulso de objetivo é chamado ActivateObjectivePulse() e requer um argumento do tipo agent. Comece criando o método para obter a instância de agent que representa seu personagem de jogador.
Declare uma função chamada
FindPlayer()definida como<private>, com um valor de retorno devoid.Obtenha uma matriz de todos os jogadores do seu nível com
Self.GetPlayspace().GetPlayers(). Armazene a matriz em uma variável chamadaAllPlayers.VerseFindPlayer<private>() : void = AllPlayers := Self.GetPlayspace().GetPlayers()Para obter a referência ao único jogador no seu nível, atribua o primeiro elemento da matriz à própria variável. O acesso a uma matriz é uma expressão falível, então coloque-a em uma expressão
if.Verseif (FirstPlayer := AllPlayers[0]):Como a atribuição do seu
playera uma variável pode falhar, você deve usar uma variável do tipo option ao fazer referência ao jogador no seu código. Declare uma variável de jogador opcional?player. Ela deve ser compatível com suas outras variáveis de membro.Verseobjective_coordinator_device<public> := class<concrete>(creative_device): var PlayerOpt<private> : ?player = false @editable PickupMarker<public> : objective_marker = objective_marker{} # Where the marker will be moved to @editable Destination<public> : transform = transform{}Defina sua nova variável e crie um bloco
elsecom uma expressãoPrint()que informará se um jogador não foi encontrado. Sua funçãoFindPlayer()agora está completa.VerseFindPlayer<private>() : void = # Since this is a single player experience, the first player [0] # should be the only one available. AllPlayers := Self.GetPlayspace().GetPlayers() if (FirstPlayer := AllPlayers[0]): set PlayerOpt = option{FirstPlayer} Print("Player found")
Novamente na função OnBegin(), você precisa fazer mais duas alterações:
Chame a função
FindPlayer().VerseOnBegin<override>()<suspends> : void = FindPlayer()Depois de chamar
MoveMarker(), use outra expressãoifpara definir sua variável opcional de jogador como uma nova variável e a transmita como argumento paraPickupMarker.MapIndicator.ActivateObjectivePulse()Verseif (FoundPlayer := PlayerOpt?): PickupMarker.MapIndicator.ActivateObjectivePulse(FoundPlayer)
Se você executar seu código agora, verá o pulso de objetivo apontando do seu personagem para a localização do marcador de objetivo no nível!
Código completos
Objective_marker.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Fortnite.com/Devices/CreativeAnimation }
objective_marker<public> := struct<concrete>:
# The prop that will be moved
@editable
RootProp<public> : creative_prop = creative_prop{}
Objective_coordinator_device.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /Fortnite.com/Playspaces }
using { /UnrealEngine.com/Temporary/SpatialMath }
objective_coordinator_device<public> := class<concrete>(creative_device):
var PlayerOpt<private> : ?player = false
@editable
Por si só
Lembre-se de que o código de movimento que você criou aqui funciona para qualquer adereço. Se você conseguir transformar um adereço móvel no pai de um dispositivo, esse dispositivo se moverá com ele. Tente mover outros adereços e dispositivos e veja se consegue pensar em outros jogos que possam usá-los.
Próximas etapas
Se você está usando este guia para criar o jogo Retirada/Entrega, sua próxima etapa é aprender a criar a funcionalidade de Temporizador de contagem regressiva.