Guia do programador do Cloud Scripting
Este guia descreve como usar a API de script do Mesh Cloud 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 Definir infraestrutura de script de nuvem 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 conduzem 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 de jogo ao qual o componente Mesh Cloud Scripting está anexado. As seguintes classes da API do Mesh Cloud Scripting mapeiam um para um com objetos Unity criados no editor:
- GameObject (componente & Transform) -> TransformNode
- Componente Light -> 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 Mesh Collider -> 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 esfera anexado, 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 Unity para o DOM de malha
Você pode criar uma cena com componentes que a API de script do Mesh Cloud não conhece. Eles simplesmente não existirão no DOM de script de nuvem de malha 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 de GameObject/componente; no entanto, o Mesh Cloud Scripting DOM tem uma única estrutura de árvore. Um TransformNode na API de script de nuvem de malha tem filhos que podem ser outros TransformNodes ou podem ser outros nós mapeados para componentes. Podemos considerar esta uma lista mesclada dos componentes do objeto de jogo associado e os filhos de seu componente de transformação.
Transformada Rect
Se você adicionar um componente que usa um RectTransform, por exemplo, o componente Text Mesh Pro, o objeto de jogo não aparecerá como um nó no gráfico de cena do Mesh Cloud Scripting. Ainda é possível mover, ativar e desativar esse componente, mas para isso, é necessário envolver o objeto de jogo usando RectTransform em outro objeto de jogo usando o componente Transform regular.
Eventos de alteração de propriedade
Você pode assinar 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 inscrever-se em todos os eventos inscrevendo-se DomObjectPropertyChanged
no 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 serão visíveis na cena até que sejam explicitamente adicionados como uma criança à cena ou a um de seus descendentes. Da mesma forma, definir o pai de um nó como nulo irá removê-lo 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 desativará 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 irá habilitá-los 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 redefinir nós que correspondem aos componentes Unity. Isso é implementado recriando esses componentes Unity com base nas representações do Nó de Script de Nuvem Mesh. Somente os nós que podem ser criados por meio da API de script do Mesh Cloud podem ser clonados ou reparentados. Se você criou um componente no Unity e definiu campos que não são refletidos no nó de script de nuvem de malha correspondente, esses campos serão redefinidos para seus padrões se o próprio nó for clonado. Por esse motivo, recomendamos que você clone ou redirecione os nós de transformação onde estiver manipulando objetos criados no Unity. Estes sempre manterão corretamente todas as configurações originais do Unity.
Utilizadores
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 que o usuário saia e volte a ingressar. O nome de exibição do usuário também pode ser acessado através do User.DisplayName
. A ID do evento a partir da qual o usuário se conectou pode ser acessada por meio User.ConnectedEventId
do .
Durante o desenvolvimento, o nome de exibição do usuário, o identificador e o ID do evento podem ser simulados no editor do componente Mesh Cloud Scripting nas "Configurações do desenvolvedor", conforme mostrado abaixo.
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 detetar colisões com volumes de gatilho.
Caixas de diálogo de informações
É possível no Mesh Cloud Scripting abrir 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 de 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 tags de rich text podem ser usadas na mensagem para controlar as propriedades do texto (por exemplo, cor ou negrito).
Classes
Aplicação na 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:
WebSlateNode
O WebSlate é um componente Unity personalizado que faz parte do pacote do kit de ferramentas Mesh. Para adicionar um pré-fabricado 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 quad deste pré-fabricado.
Um exemplo é mostrado abaixo, onde um pré-fabricado 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");
Escutar 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
por 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 clique
É possível descobrir qual usuário clicou no colisor observando os argumentos de evento de alteração de propriedade. Você também pode ler o contato normal e a posição do clique a partir dos argumentos do evento. Essas coordenadas serão relativas ao espaço de coordenadas locais do InteractableNode.
Animadores
Você pode criar e adicionar um Unity Animator à 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 Animator 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 filho do TransformNode correspondente. Usando a API dessa classe, você pode controlar o Animator.
O modelo de programação do Mesh Cloud Scripting é autorizado pelo servidor e suportamos 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 de servidor. Por esse motivo, apenas a seguinte API é suportada atualmente:
- 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 através de transições.
- Configuração de variável float: apenas variáveis float são expostas, e apenas com a finalidade de ligação a "Motion Time" em um animador.
- Configuração da velocidade da camada
Dentro de um estado, você pode criar um clipe de animação sem restrições sobre os valores que 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 pelo AnimationNodes:
- Transições: se você adicionar transições ao seu Animator, não poderá acioná-las por meio da API de script do Mesh Cloud (o servidor não modela transições).
- Variáveis (exceto flutuações para conduzir o tempo de movimento). Não há suporte para variáveis usadas para impulsionar a lógica de transição ou multiplicadores de velocidade.
- Estados espelhados, deslocamento de ciclo e IK de pé.
Late Join 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 duração sendo reproduzida em um estado, o tempo de reprodução será definido para a hora atual correta da animação na associação tardia. No entanto, se o seu estado disparar eventos, estes NÃO serão disparados no cliente que se juntou tardiamente. Alguns outros cenários podem não funcionar como esperado; por exemplo, se você acionar um som habilitando um AudioSource no início de um estado, esse AudioSource ainda estará 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 que tenham estados padrão que não façam 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.
Reparentalidade e clonagem do animador
AnimationNodes não pode ser criado por meio da API de script do Mesh Cloud. A única maneira de criar um AnimationNode é exportando uma cena Unity que contém um componente Animator. Se você tentar clonar ou redefinir a matriz do 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 contém o que pode ser clonado e parental.
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 isso, é possível criar animadores que não geram 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(ões).
LightNode
PointLightNode, DirectionalLightNode e SpotLightNode mapeiam 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 do 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 de script de nuvem de malha para seus padrões.
GeometryNode
BoxGeometryNode, SphereGeometryNode, CapsuleGeometryNode e MeshGeometryNode mapeiam para o Componente Box Collider do Unity, o Componente do Colisor de Esfera, o Componente do Colisor da Cápsula e o Componente do Colisor de Malha, respectivamente. Eles também podem ser criados por meio da API Mesh Cloud Scripting. Ativar e desativar os nós de geometria irá adicioná-los e removê-los dos candidatos a acertos se um MeshInteractableSetup estiver anexado ao seu 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 nenhum e isTrigger será definido como false).
RigidBodyNode
Adicionar um componente Rigidbody a um objeto colocará seu movimento sob o controle da Mesh Physics. Sem adicionar qualquer código, um objeto Rigidbody será puxado para baixo pela gravidade e reagirá a colisões com outros objetos.
Nota: GeometryNode.Friction
irá regressar staticFriction
. No entanto, se definido no lado do Mesh Cloud Scripting, ele será atualizado tanto quanto staticFriction
dynamicFriction
nos clientes.
Volumes de gatilho
Os nós de geometria podem atuar como volumes de gatilho 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 irá gerar Entered
e Exited
para quaisquer Avatares que iniciem/parem de se sobrepor a ela.
Nota: O objeto Unity precisa ser adicionado à TriggerVolume
camada para permitir que o feixe de teletransporte o ignore, já que colisores na camada bloqueiam o Default
feixe de teletransporte.
Nó de texto
O TextNode é mapeado para o componente TextMeshPro do Unity. Se você adicionar um componente TextMeshPro à sua cena, haverá um TextNode correspondente na hierarquia de 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. Atualmente, não é possível criar um TextNode através da API; você deve criá-los adicionando-os à sua cena em Unity. Além disso, você não pode clonar um TextNode diretamente — em vez disso, você deve clonar o TranformNode pai do TextNode.
Malhas
Atualmente, as malhas são componentes "ocultos" para a API de script do Mesh Cloud. 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 Máquina de Script Unity à 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 máquina de script encontrada, 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 à máquina de script do Mesh Cloud Scripting. Ao adicionar a Máquina de Script como um componente a um GameObject no Unity, você encontrará uma instância correspondente da classe gerada como filho do TransformNode correspondente. Usando a API dessa classe, você pode controlar as variáveis do Script Machine.
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 Mesh Cloud Scripting.
- A opção "Enable 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 levantado anteriormente sobre os outros clientes não será gerado no cliente que ingressou tardiamente. Alguns outros cenários podem não funcionar como esperado; por exemplo, se você acionar um som habilitando um AudioSource em resposta a um evento On State Changed , esse AudioSource ainda estará 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 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 redefinir o VisualScriptNode, receberá um erro porque não há como dar suporte a essa ação. Ainda é possível clonar ou reparentar o pai do VisualScriptNode, pois isso corresponde ao Unity GameObject que contém o que pode ser clonado e parental.
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. Por 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(ões).
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, você precisa adicioná-lo como um recurso incorporado em seu 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 diretamente ao arquivo .csproj:
<EmbeddedResource Include="<my_resource_file>" CopyToOutputDirectory="PreserveNewest" />
Observe que é assim que o scene.map é empacotado, o 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.Rotation
RigidBody.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 forem definidas no Mesh Cloud Scripting Service. Observe que alterar 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 a partir 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 clientes. Nota: Corpo rígido clonado terá posição, rotação e velocidades desde o início da cena do corpo rígido original. Se estes devem ser diferentes, eles devem ser definidos explicitamente no Mesh Cloud Scripting.