sexta-feira, 25 de agosto de 2023

UEFN Verse: Programando um rotacionador de Props com spawn

Eu ainda estou programando o projeto de exemplo que usarei na Parte 2 dos meus tutoriais de programação em Verse. Por causa disso resolvi compartilhar uma dica rápida de Verse com vocês.

Neste artigo vamos programar um rotacionador de Props. Props são itens  que podem ser adicionados a um nível do Fortnite. Os Props são muito utilizados na montagem do cenário e a maioria deles podem ser destruídos para fornecer materiais para o jogador.

É um exemplo simples mas que será útil para mostrar alguns recursos interessantes da linguagem Verse em ação.

Em qualquer projeto UEFN, abra o Verse Explorer, clique com o botão-direito no nome do projeto e escolha a opção Add new Verse file to project.

Em Device Name coloque props_rotator e clique no botão Create para usar o código do template.

No início do arquivo adicione o módulo SpatialMath e crie uma constante com o nome TimeRot180 do tipo float com valor default de 2.0, como mostra o código abaixo:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath}

props_rotator := class(creative_device):

    @editable
    TimeRot180 : float = 2.0

O módulo SpatialMath é necessário porque usaremos uma função chamada ApplyYaw() que modifica a rotação ao redor do eixo Z.

A constante TimeRot180 armazena o tempo em segundos que um Prop levará para dar meia volta (180 graus).

Vamos criar uma função chamada RotateProp que receberá um creative_prop como parâmetro e irá manter este Prop rotacionando.

Esta função precisa ser assíncrona, por isso usaremos o especificador suspends.

O código da função RotateProp é este:

    RotateProp(Prop : creative_prop)<suspends>:void=

        loop:
            PropTransform := Prop.GetTransform()
            PropLocation  := PropTransform.Translation
            PropRotation  := PropTransform.Rotation

            NewRotation := PropRotation.ApplyYaw(180.0)

            Prop.MoveTo(PropLocation, NewRotation, TimeRot180)

A função RotateProp obtém a estrutura transform do Prop para ter acesso à localização e rotação atual do Prop. É usada a função ApplyYaw para criar uma nova rotação que modifica a rotação atual do Prop em 180 graus ao redor do eixo Z.

Usaremos a função MoveTo da classe creative_prop para que o Prop modifique a sua rotação ao longo do tempo que está armazenado na constante TimeRot180. Quando o Prop completar a rotação, a expressão loop executará o bloco de código novamente fazendo com que o Prop rotacione continuamente.

Observe que a expressão loop que repete o bloco de código responsável pela rotação não tem nenhuma expressão break ou return para encerrar o loop, ou seja, é um loop infinito.

Um código assim em outras linguagens de programação que não possui contexto assíncrono provavelmente irá travar seu computador ao ser executado. Mas como veremos na linguagem Verse é muito simples criar um contexto assíncrono independente para executar esta função sem interromper o fluxo de execução do jogo. 

Para completar o código do dispositivo props_rotator, defina um array de creative_prop e modifique a função OnBegin para ficar desta forma:

    @editable
    PropsToRotate : []creative_prop = array{}

    OnBegin<override>()<suspends>:void=
       
        for (PropInstance : PropsToRotate):
            spawn{ RotateProp(PropInstance) }

Na função OnBegin temos a expressão for que irá repetir o bloco de código abaixo dela para cada elemento do array.

A expressão spawn inicia uma expressão assíncrona (a função RotateProp) e continua a execução do fluxo principal. Para cada um dos Props que forem adicionados ao array haverá um contexto assíncrono executando a função RotateProp.

A expressão spawn é um tipo de concorrência não estruturada. A recomendação na linguagem Verse é a de tentar usar as expressões de concorrência estruturadas como sync, race, rush e branch. O spawn deve ser usado como último recurso em alguns casos específicos.

O código Verse completo do dispositivo props_rotator fica assim:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath}

props_rotator := class(creative_device):

    @editable
    TimeRot180 : float = 2.0

    @editable
    PropsToRotate : []creative_prop = array{}

    OnBegin<override>()<suspends>:void=
       
        for (PropInstance : PropsToRotate):
            spawn{ RotateProp(PropInstance) }  
                
    RotateProp(Prop : creative_prop)<suspends>:void=

        loop:
            PropTransform := Prop.GetTransform()
            PropLocation  := PropTransform.Translation
            PropRotation  := PropTransform.Rotation

            NewRotation := PropRotation.ApplyYaw(180.0)

            Prop.MoveTo(PropLocation, NewRotation, TimeRot180)  

Salve o arquivo e compile o código Verse usando a opção Verse > Build Verse Code do menu do UEFN.

Adicione o props_rotator e alguns Props no nível para serem rotacionados pelo nosso dispositivo. Uma boa opção para visualizar a rotação é o Prop com nome Farm_WeatherVane_01.

Selecione o props_rotator no nível e na aba Details adicione algumas referências de Props no array PropsToRotate. Você também pode alterar o tempo de rotação na propriedade TimeRot180.



Salve o nível e inicie a sessão. Observe a rotação dos Props que foram adicionados ao PropsToRotate



Sumário Verse