Compartilhar via


Guia do programador de Cloud Scripting

Este guia descreve como usar a API do Mesh Cloud Scripting e as ferramentas de desenvolvedor para criar ambientes (eles começam como projetos no Unity e, em seguida, são carregados em uma coleção Mesh). Recomendamos que você leia primeiro a infraestrutura Set cloud Scripting no Azure para se familiarizar com os conceitos e a arquitetura básica do Mesh Cloud Scripting.

Esta seção descreve os recursos e a interface da API Mesh Cloud Scripting, que é usada para escrever os scripts que impulsionam comportamentos em ambientes.

Estrutura básica do DOM

A estrutura DOM espelha a estrutura da sua cena Unity. O membro "Scene" do aplicativo corresponde ao objeto do jogo ao qual seu componente Mesh Cloud Scripting está conectado. As seguintes classes de API do Mesh Cloud Scripting mapeiam um para um com objetos Unity criados no editor:

  • GameObject (& Transform Component) -> TransformNode
  • Componente de luz -> PointLightNode, SpotLightNode, DirectionalLightNode
  • Componente Animador -> AnimationNode (e classes derivadas, veja abaixo)
  • Componente Box Collider -> BoxGeometryNode
  • Componente Sphere Collider -> SphereGeometryNode
  • Componente Colisor de Cápsulas -> CapsuleGeometryNode
  • Componente Colisor de Malha -> MeshGeometryNode
  • Componente Text Mesh Pro -> TextNode
  • Componente Rigidbody -> RigidBodyNode

Por exemplo, se você criar uma cena com um objeto de jogo que tenha um componente Light (definido como uma luz pontual) e um colisor de esferas conectado, sua cena conterá um TransformNode com dois filhos: um PointLightNode e um SphereGeometryNode.

Além disso, alguns objetos da API do Mesh Cloud Scripting não têm componentes Unity internos correspondentes. Esses são componentes adicionais que você pode criar no Unity que fazem parte do pacote do kit de ferramentas Mesh.

  • Componente Mesh Cloud Scripting (Descrito acima)
  • Componente WebSlate

Mapeando o DOM de unidade para o DOM de malha

Você pode criar uma cena com componentes que a API do Mesh Cloud Scripting não conhece. Eles simplesmente não existirão no DOM do Mesh Cloud Scripting para a cena. No entanto, a estrutura de cena completa de GameObjects será espelhada na API DOM como TransformNodes.

Unity tem uma forma de API GameObject/componente; no entanto, o DOM do Mesh Cloud Scripting tem uma única estrutura de árvore. Um TransformNode na API do Mesh Cloud Scripting tem filhos que podem ser outros TransformNodes ou podem ser outros nós mapeados para componentes. Podemos considerar isso uma lista mesclada dos componentes do objeto de jogo associado e os filhos de seu componente de transformação.

Rect Transform

Se você adicionar um componente que usa um RectTransform, por exemplo, o componente Text Mesh Pro, o objeto do jogo não aparecerá como um Nó no gráfico de cena do Mesh Cloud Scripting. Ainda é possível mover, habilitar e desabilitar esse componente, mas para isso, é necessário encapsular o objeto de jogo usando RectTransform em outro objeto de jogo usando o componente Transform regular.

Eventos de alteração de propriedade

Você pode se inscrever em eventos de alteração de propriedade chamando AddPropertyChangedEventHandler qualquer nó na hierarquia. Você deve passar o nome da propriedade como uma cadeia de caracteres.

Também é possível se inscrever em todos os eventos assinando o DomObjectPropertyChanged evento. Isso é chamado quando qualquer propriedade no DOM é alterada.

Ciclo de vida do objeto

Os nós, quando criados, não são parentais. Isso significa que eles não estarão visíveis na cena até que sejam explicitamente adicionados como uma criança à cena ou um de seus descendentes. Da mesma forma, definir o pai de um nó como null removerá ele e seus descendentes da cena.

Às vezes, você deseja desativar um nó temporariamente, mas não manter um registro de onde ele estava na cena. Por esse motivo, cada nó tem um sinalizador "ativo". Quando definido como false, ele desabilitará o nó e seus descendentes.

Você pode criar objetos e componentes de jogo no Unity que fazem parte da cena, mas estão desativados. Eles aparecerão como Nós na hierarquia de cena do Mesh Cloud Scripting, mas terão seu sinalizador ativo definido como false. Definir o sinalizador ativo como true os habilitará na cena Unity.

Clonagem e reparentalidade

Os nós podem ser clonados e reparentados na API Mesh Cloud Scripting; a cena Unity correspondente será atualizada de acordo. Se você clonar um nó, ele clonará esse nó e todos os seus filhos (incluindo filhos que podem estar nos objetos Unity correspondentes, mas não são visíveis para o Mesh Cloud Scripting).

É possível clonar ou recriar nós que correspondem aos componentes Unity. Isso é implementado recriando esses componentes Unity com base nas representações do Mesh Cloud Scripting Node. Somente nós que podem ser criados por meio da API Mesh Cloud Scripting podem ser clonados ou reparentados. Se você criou um componente no Unity e definiu campos que não são refletidos no Mesh Cloud Scripting Node, esses campos serão redefinidos para seus padrões se o próprio Nó for clonado. Por esse motivo, recomendamos que você clone ou represente novamente os nós de transformação nos quais estiver manipulando objetos criados no Unity. Eles sempre manterão corretamente todas as configurações originais do Unity.

Usuários

Há vários locais na API que fornecem propriedades de usuário. A User.Identifier propriedade é uma cadeia de caracteres de identificador persistente que é persistente para o usuário, mesmo se o usuário sair e ingressar novamente. O nome de exibição do usuário também pode ser acessado por meio do User.DisplayName. A ID do evento a partir da qual o usuário se conectou pode ser acessada por meio User.ConnectedEventIddo .

Durante o desenvolvimento, o nome de exibição do usuário, o identificador e a ID do evento podem ser simulados no editor de componentes do Mesh Cloud Scripting nas "Configurações do desenvolvedor", conforme mostrado abaixo.

Propriedades de usuário fictício

Avatares

Avatares são a representação dos usuários na cena. Eles podem ser usados para teletransportar usuários para um determinado local, viajar entre cenas e detectar colisões com volumes de gatilho.

Caixas de diálogo de informações

É possível no Mesh Cloud Scripting exibir uma caixa de diálogo de espaço de tela no aplicativo Microsoft Mesh com uma mensagem personalizada. SceneNode contém uma função para isso, ShowMessageToParticipants(string message, IReadOnlyCollection<Participant> participants). Tags rich text podem ser usadas na mensagem para controlar as propriedades do texto (cor, negrito etc.).

Caixas de diálogo de entrada

O Mesh Cloud Scripting pode solicitar entrada de texto de um participante em um evento Mesh com uma mensagem personalizada. CloudApplication fornece o método Task<string> ShowInputDialogToParticipantAsync(string message, Participant participant, CancellationToken token). As marcas rich text podem ser usadas na mensagem para controlar as propriedades do texto (por exemplo, cor ou negrito).

Classes

Aplicativo em nuvem

A ICloudApplication interface é o ponto de partida para o desenvolvimento de aplicativos Mesh. Está disponível em "App.cs" como a variável _app. Além da cena, ICloudApplication tem funções de criação para todos os tipos disponíveis. Ele também tem uma série de outros métodos, mas eles são para uso interno.

InteractableNode

O MeshInteractableSetup é um componente Unity personalizado que faz parte do pacote do kit de ferramentas Mesh. Quando você o anexa a um objeto de jogo no Unity, ele gera eventos de clique quando qualquer usuário clica em qualquer um dos colidíveis ativos nesse objeto de jogo ou em seus filhos.

Um exemplo simples é mostrado abaixo, onde o componente MeshInteractableSetup é adicionado ao mesmo objeto de jogo que o colisor de caixa:

Exemplo de entrada simples

WebSlateNode

O WebSlate é um componente Unity personalizado que faz parte do pacote do kit de ferramentas Mesh. Para adicionar um pré-fabricado do WebSlate à sua cena, selecione GameObject>Mesh Toolkit>WebSlate na barra de menus. O site atribuído à propriedade URL da instância do WebSlate é renderizado no quádruplo dessa pré-fabricação.

Um exemplo é mostrado abaixo, onde um pré-fabricado do WebSlate foi adicionado à cena e atribuído um Url:

        var webSlateNode = Root.FindFirstChild<WebSlateNode>(true);
        webSlateNode.Url = new System.Uri("https://en.wikipedia.org/wiki/Color");

Exemplo de WebSlate

Ouvindo cliques

Aqui está um script simples do Mesh Cloud Scripting que gira o cubo cada vez que ele é clicado. Substitua o método stub StartAsync dentro App.cs com este código.

        private float _angle = 0;

        public Task StartAsync(CancellationToken token)
        {
            // First we find the TransformNode that corresponds to our Cube gameobject
            var transform = _app.Scene.FindFirstChild<TransformNode>();

            // Then we find the InteractableNode child of that TransformNode
            var sensor = transform.FindFirstChild<InteractableNode>();

            // Handle a button click
            sensor.Selected += (_, _) =>
            {
                // Update the angle on each click
                _angle += MathF.PI / 8;
                transform.Rotation = new Rotation { X = 1, Y = 0, Z = 0, Angle = _angle };
            };

            return Task.CompletedTask;
        }

Informações de Hit

É possível descobrir qual usuário clicou no colisor observando os argumentos do evento de alteração de propriedade. Você também pode ler o contato normal e a posição do clique nos argumentos do evento. Essas coordenadas serão relativas ao espaço de coordenadas local do InteractableNode.

Animadores

Você pode criar e adicionar um Unity Animator à sua cena e controlá-la através do Mesh Cloud Scripting. O plugin do kit de ferramentas Mesh examinará os ativos em seu projeto Unity e, para cada Animador encontrado, ele gerará uma classe em uma pasta "AnimationScripts" em seu projeto Mesh Cloud Scripting. Essa classe deriva de AnimationNode e pode ser usada para controlar o Animator a partir do Mesh Cloud Scripting. Ao adicionar o Animator como um componente a um objeto de jogo no Unity, você encontrará uma instância correspondente da classe gerada como um filho do TransformNode correspondente. Usando a API dessa classe, você pode controlar o Animator.

O modelo de programação do Mesh Cloud Scripting é autoritativo do servidor e oferecemos suporte a apenas um pequeno subconjunto da funcionalidade do Animator. Isso ocorre porque modelamos o Animator no servidor e esperamos que todos os clientes sincronizem com precisão com o modelo do servidor. Por esse motivo, somente a seguinte API é suportada no momento:

  • Configuração de estado (para cada camada, há uma propriedade correspondente na classe que pode ser definida como um enum com base nos estados disponíveis no Animator). Os estados são definidos imediatamente, não por meio de transições.
  • Configuração de variável float: somente variáveis float são expostas, e somente com a finalidade de vincular a "Motion Time" em um Animator.
  • Configuração de velocidade da camada

Dentro de um estado, você pode criar um clipe de animação sem restrições sobre quais valores você pode definir na cena Unity. Clipes de animação em loop também são suportados. Os seguintes recursos do Animators não são suportados por meio do AnimationNodes:

  • Transições: se você adicionar transições ao seu Animator, não poderá acioná-las por meio da API do Mesh Cloud Scripting (o servidor não modela transições).
  • Variáveis (exceto flutuações para acionar o tempo de movimento). Não há suporte para variáveis usadas para direcionar a lógica de transição ou multiplicadores de velocidade.
  • Estados espelhados, deslocamento de ciclo e IK de pé.

Ingresso tardio e animadores

Quando os clientes ingressam em um Evento Mesh, eles sincronizam com o estado atual e a hora local de todos os Nós de Animação em execução. Se você tiver uma animação de longa execução sendo reproduzida em um estado, o tempo de reprodução será definido como a hora atual correta da animação na junção tardia. No entanto, se o seu estado disparar eventos, estes NÃO serão disparados no cliente ingressado tardiamente. Alguns outros cenários podem não funcionar conforme o esperado; por exemplo, se você acionar um som habilitando um AudioSource no início de um estado, esse AudioSource ainda será habilitado no cliente de ingresso tardio, mas começará a ser reproduzido no início do clipe de áudio.

Estado inicial do animador

Recomendamos que você crie animadores com estados padrão que não fazem nada. Quando uma cena começa a ser reproduzida no Unity, ela ativa todos os animadores e começa a reproduzir suas animações padrão. Isso pode acontecer antes que a conexão do Mesh Cloud Scripting Service ocorra; Portanto, não há como sincronizar esses estados e o comportamento pode não ser o desejado.

Reparentalização e clonagem do animador

AnimationNodes não pode ser criado por meio da API Mesh Cloud Scripting. A única maneira de criar um AnimationNode é exportando uma cena Unity que contém um componente Animator. Se você tentar clonar ou criar novamente o AnimationNode, receberá um erro porque não há como dar suporte a essa ação. Ainda é possível clonar ou recriar o pai do AnimationNode, pois isso corresponde ao Unity Game Object que pode ser clonado e pai.

Notas sobre o código gerado

O código gerado removerá espaços de nomes de Animadores, Camadas, Estados e Variáveis; por exemplo, o nome da variável "my var" torna-se "myVar" no código. Por causa disso, é possível criar animadores que não gerarão código válido. Por exemplo, se você tiver duas variáveis chamadas "my var" e "myVar", você receberá um erro durante a geração e uma mensagem solicitando que você renomeie a(s) variável(is).

LightNode

PointLightNode, DirectionalLightNode e SpotLightNode são mapeados para o componente Unity Light (que terá seu tipo definido para o valor correspondente). É possível definir os parâmetros básicos dessas luzes através das APIs LightNode. Também é possível criar Luzes manualmente através da API. A criação de nós leves por meio da API deixará os parâmetros que não são configuráveis por meio da API Mesh Cloud Scripting para seus padrões.

GeometryNode

BoxGeometryNode, SphereGeometryNode, CapsuleGeometryNode e MeshGeometryNode mapeiam para o Componente Box Collider do Unity, o Componente Sphere Collider, o Capsule Collider Component e o Mesh Collider Component, respectivamente. Eles também podem ser criados por meio da API Mesh Cloud Scripting. Habilitar e desabilitar os Nós de Geometria os adicionará e removerá dos candidatos a visitas se um MeshInteractableSetup estiver anexado ao objeto de jogo ou a um de seus pais.

A criação de nós de geometria por meio da API deixará os parâmetros que não são configuráveis por meio da API Mesh para seus padrões (por exemplo, Material de Física será definido como none e isTrigger será definido como false).

RigidBodyNode

Adicionar um componente Rigidbody a um objeto colocará seu movimento sob o controle da Física da Malha. Sem adicionar nenhum código, um objeto Rigidbody será puxado para baixo pela gravidade e reagirá a colisões com outros objetos.

Obs.: GeometryNode.Friction retornará staticFriction. No entanto, se definido no lado do Mesh Cloud Scripting, ele atualizará ambos e staticFriction dynamicFriction nos clientes.

Volumes de gatilho

Os nós de geometria podem atuar como volumes de disparo quando sua IsTrigger propriedade é definida como true. Esse sinalizador corresponde à IsTrigger propriedade no colisor em Unity e não pode ser alterado em tempo de execução. Quando a geometria é um gatilho ele irá gerar Entered e Exited para quaisquer Avatares que iniciam/param sobrepondo-se a ele.

Nota: O objeto Unity precisa ser adicionado à TriggerVolume camada para permitir que o feixe de teletransporte o ignore, já que os colisores na camada bloqueiam o Default feixe de teletransporte.

TextNode

O TextNode é mapeado para o componente TextMeshPro do Unity. Se você adicionar um componente TextMeshPro à sua cena, haverá um TextNode correspondente na hierarquia da cena do Mesh Cloud Scripting. Isso permite que você defina o texto do componente em tempo de execução. Você também pode alterar as propriedades básicas do texto por meio da API TextNode — negrito, itálico, sublinhado, tachado e cor. No momento, não é possível criar um TextNode por meio da API; você deve criá-los adicionando-os à sua cena em Unity. Além disso, você não pode clonar um TextNode diretamente — você deve, em vez disso, clonar o TranformNode pai do TextNode.

Malhas

As malhas são atualmente componentes "ocultos" para a API do Mesh Cloud Scripting. Eles podem ser criados no editor Unity e podem ser manipulados manipulando seus objetos de jogo pai/componentes Transform, mas não podem ser criados programaticamente, nem suas propriedades podem ser editadas em tempo de execução por meio da API Mesh.

Scripts visuais

Você pode criar e adicionar uma Unity Script Machine à sua cena e controlá-la através do Mesh Cloud Scripting. O plug-in do kit de ferramentas Mesh examinará os ativos em seu projeto Unity e, para cada Script Machine encontrado, ele gerará uma classe em uma pasta "VisualScripts" em seu projeto Mesh Cloud Scripting. Essa classe deriva de VisualScriptNode e pode ser usada para manipular as variáveis Unity associadas ao Script Machine do Mesh Cloud Scripting. Ao adicionar o Script Machine como um componente a um GameObject no Unity, você encontrará uma instância correspondente da classe gerada como um filho do TransformNode correspondente. Usando a API dessa classe, você pode controlar as variáveis da Máquina de Script.

Sincronização de estado

Por padrão, o Mesh replica automaticamente as alterações de cena feitas por scripts visuais em um cliente para todos os outros clientes. Para que o Mesh Cloud Scripting esteja ciente de uma alteração feita por meio de scripts visuais, as seguintes pré-condições devem ser atendidas:

  • O componente Script Machine está em um GameObject que é um descendente da raiz da cena do Mesh Cloud Scripting.
  • A opção "Ativar Visual Scripting" do componente Mesh Cloud Scripting está ativada.

Se uma das condições acima não for atendida, o tempo de execução do Mesh Visual Scripting continuará a replicar as alterações de cena, mas o Mesh Cloud Scripting permanecerá alheio a essas alterações.

Estado inicial

Recomendamos que seus scripts visuais não modifiquem ou dependam do estado compartilhado na inicialização. O evento On Start normalmente acontece antes da conexão do Mesh Cloud Scripting Service ocorrer, portanto, não há como sincronizar o estado nesse momento, e o comportamento pode não ser o desejado.

Adesão tardia

Quando os clientes ingressam em um evento Mesh, eles sincronizam com o estado atual de todos os nós do Visual Script. Qualquer evento de alteração de estado que possa ter sido gerado anteriormente nos outros clientes não será gerado no cliente ingressado tardiamente. Alguns outros cenários podem não funcionar conforme o esperado; por exemplo, se você acionar um som habilitando um AudioSource em resposta a um evento On State Changed , esse AudioSource ainda será habilitado no cliente de ingresso tardio, mas começará a ser reproduzido no início do clipe de áudio.

Reparentalidade e clonagem

O VisualScriptNode não pode ser criado por meio da API do Mesh Cloud Scripting. A única maneira de criar um VisualScriptNode é exportando uma cena Unity que contém um componente Script Machine. Se você tentar clonar ou criar novamente o VisualScriptNode, receberá um erro porque não há como dar suporte a essa ação. Ainda é possível clonar ou recriar o pai do VisualScriptNode, pois isso corresponde ao UnityGameObject que pode ser clonado e pai.

Notas sobre o código gerado

O código gerado removerá espaços de nomes de Máquinas de Script e variáveis; por exemplo, o nome da variável "my var" torna-se "MyVar" no código. Devido a isso, é possível criar máquinas de script que não gerarão código válido. Por exemplo, se você tiver duas variáveis chamadas "my var" e "myVar", você receberá um erro durante a geração e uma mensagem solicitando que você renomeie a(s) variável(is).

Outros tópicos do Mesh Cloud Scripting

Adicionando recursos ao Mesh Cloud Scripting Service

Se você precisar adicionar um recurso para seu Mesh Cloud Scripting Service usar, será necessário adicioná-lo como um recurso incorporado ao arquivo de projeto C#. Isso pode ser feito por meio da interface do usuário do projeto no Visual Studio ou adicionando a seguinte linha no arquivo .csproj diretamente:

<EmbeddedResource Include="<my_resource_file>" CopyToOutputDirectory="PreserveNewest" />

Observe que é assim que o scene.map é empacotado, que você pode ver no arquivo .csproj para referência.

Trabalhando com Física de Malha

Mesh Physics terá o cuidado de sincronizar o movimento de corpos rígidos entre os clientes. Mesh Cloud Scripting TransformNode.Position, TransformNode.RotationRigidBody.Velocity e RigidBody.AngularVelocity não será atualizado com o estado de simulação mais recente. No entanto, os clientes aplicarão alterações se elas estiverem definidas no Mesh Cloud Scripting Service. Observe que a alteração de uma única propriedade deixará outras inalteradas. Por exemplo, se apenas a posição for definida, a velocidade não será alterada e o corpo rígido continuará o movimento com a velocidade antiga da nova posição. Dado que o Mesh Cloud Scripting Service não é atualizado com o estado de movimento mais recente para corpos rígidos, a recomendação é defini-los apenas para novos corpos rígidos.

Se TransformNode com RigidBodyNode for clonado, o corpo clonado será registrado e entregue para Mesh Physics sincronização entre os clientes. Nota: Corpo rígido clonado terá posição, rotação e velocidades a partir do início da cena de corpo rígido original. Se eles devem ser diferentes, eles devem ser definidos explicitamente no Mesh Cloud Scripting.

Próximas etapas