Compartir a través de


Procedimientos recomendados de scripting visual de malla para redes

Información general

En Mesh, la mayoría de las propiedades de la escena se comparten de forma predeterminada en todos los clientes conectados a la misma sala. Por ejemplo, la posición y la rotación de un objeto de escena, el estado habilitado de un componente o el texto de TextMeshPro.

Como regla general, las propiedades de componente y las variables object que tienen los siguientes tipos de valor se comparten automáticamente de forma predeterminada:

Los tipos de colección (listas y conjuntos) y las referencias a objetos de escena no se comparten.

Los nodos de script visual que acceden o modifican propiedades en Mesh se etiquetan con una etiqueta que indica si son "Compartidos por todos los clientes" o "Local para este cliente":

______________

Las variables de objeto también se comparten de forma predeterminada si las ha declarado con uno de los tipos de valor enumerados anteriormente:

______________

Mesh no admite variables de escena, pero puede usar componentes de variables independientes en el entorno para guardar variables que se pueden compartir independientemente de cualquier componente específico de Script Machine.

Si no desea compartir automáticamente propiedades o variables de objeto, puede agregar un componente Ámbito de script local a la escena. Esto hará que todas las propiedades de la escena y las variables de script en este objeto de juego y cualquiera de sus descendientes sean locales.

______________

Sugerencia: Puede ver varios ejemplos de cómo se usa el componente Ámbito de script local en el capítulo 3 de nuestro tutorial de Mesh 101 que se centra en el scripting visual.

En el caso de las variables de script locales que solo se usan en una sola máquina de scripts, es mejor usar variables de Graph, que nunca se comparten entre clientes mediante Mesh.

El uso compartido mediante scripting visual mesh ofrece las siguientes garantías:

  • Coherencia final garantizada: todos los clientes llegarán finalmente al mismo estado compartido.

  • Atomicidad garantizada por componente: todas las actualizaciones de las propiedades del mismo componente de escena (o el mismo componente variables ) de la misma actualización se aplicarán de forma atómica en cada cliente.

Pero:

  • Sin garantía de ordenación: las actualizaciones aplicadas por un cliente a varios componentes de escena diferentes pueden llegar a diferentes pedidos en distintos clientes.

  • Sin garantía de escalas de tiempo: Mesh intentará replicar los cambios de estado en los clientes lo más rápido posible, pero las condiciones de red pueden retrasar la llegada de cualquier actualización de estado determinada en algunos o todos los clientes.

  • Sin garantía de granularidad: es posible que cualquier cliente no vea todas las actualizaciones incrementales individuales al estado compartido. Esto puede ocurrir cuando las condiciones de red obligan al servidor mesh a limitar la velocidad de las actualizaciones. También sucede cuando un cliente se une tarde a una sala.

El estado es eventos compartidos y no

No puede enviar ni recibir mensajes de red explícitos con Mesh Visual Scripting. Esto puede ser sorprendente al principio, pero ayuda a establecer un paradigma de red que facilita el control uniforme de los cambios en tiempo de ejecución, así como la unión tardía. En lugar de los mensajes, hay un estado compartido en las propiedades de la escena y las variables de script.

Los scripts pueden responder a actualizaciones de estado compartido de forma uniforme, independientemente de si esas actualizaciones fueron realizadas por un script local o un usuario, por otro cliente que comparte la experiencia en la misma sala, o por otros clientes que ya estaban en la sala antes de unirse a él mismo.

No poder enviar explícitamente mensajes de red significa que tendrá que empezar a pensar en el estado compartido que obtiene actualizaciones en lugar de eventos compartidos que provocan actualizaciones de estado. Los eventos compartidos son consecuencia de que el estado compartido se actualiza, no lo contrario.

Afortunadamente, Mesh Visual Scripting facilita que los scripts visuales reaccionen a las actualizaciones de estado. Use el nodo de eventos On State Changed y conecte sus entradas del lado izquierdo con cualquier variable de script o propiedad de componente que quiera observar para los cambios y el nodo de eventos desencadenará el script (conectado a su lado derecho) siempre que cualquiera de las variables o propiedades conectadas a él cambie su valor.

______________

Esto funciona con el estado compartido, así como con el estado local. El evento On State Changed se desencadenará independientemente de si el cliente local cambió las variables o propiedades que observa, por un cliente remoto o incluso por un cliente remoto antes de que el cliente local se uniera a la sala.

El uso de On State Changed para responder a los cambios de estado es eficaz: no hay ningún costo de rendimiento ni ancho de banda inactivo. Puede tener cualquier número de scripts visuales escuchando pasivamente las actualizaciones de estado de esta manera sin afectar negativamente al uso de ancho de banda o velocidad de fotogramas de su entorno.

Unión tardía

La unión tardía se produce cuando un cliente se une a una sala que ya tiene otros clientes conectados a él.

En la unión tardía, Mesh recibe el estado actual de la sala del servidor, por ejemplo, quién ya está en la sala y dónde se encuentran actualmente sus avatares, y prepara rápidamente la versión local del cliente de unión del entorno compartido para que coincida con el estado compartido por todos los usuarios de la sala.

Para una gran parte, Mesh Visual Scripting hace lo mismo. Las propiedades de componente compartido y las variables de script visual que se cambiaron en la sala antes de que el cliente se actualicen localmente para que coincidan con el estado compartido y, a continuación, se desencadenan los nodos de evento On State Changed que observan estas propiedades o variables.

Los combinaciones tardías no reproducen eventos compartidos: obtienen el estado compartido.

Desde el punto de vista del cliente local, el entorno siempre evoluciona a partir de su estado inicial que tenía justo después de cargar la escena que ha cargado en Mesh. En el caso de la unión tardía, el primer cambio de estado puede ser mayor que lo que sucede mientras el usuario local interactúa con la sala en una sesión en curso, pero es exactamente lo mismo en principio.

Todo esto sucede cuando el entorno se carga antes de que se desvanezca de negro. Tan pronto como el usuario pueda ver e interactuar con el entorno, la unión tardía ya se ha realizado.

Hacer que el estado local siga el estado compartido

A menudo, el "estado compartido" que un usuario puede observar en un entorno es realmente una combinación de estado compartido directamente por Mesh y el estado local establecido por scripts visuales en respuesta a un evento que se produjo en la sala. Por ejemplo, cuando un usuario voltea un modificador en el entorno (estado compartido), un script visual podría cambiar el color del skybox (estado local). Es posible que tenga la tentación de aplicar el cambio local (actualizar el color del skybox) directamente en respuesta al usuario que interactúa con el modificador. Sin embargo, incluso si el evento de interacción se produce en todos los clientes que están actualmente en la sala, cualquier cliente que se una a la sala más adelante no obtendrá ese evento simplemente porque no estaban allí cuando se produjo. En su lugar, debe hacer que el estado local siga el estado compartido de la siguiente manera:

  1. Cuando el usuario interactúa (por ejemplo, voltea el modificador), convierta este desencadenador en un evento local que actualice una variable compartida (por ejemplo, el estado de encendido y apagado del conmutador).
  2. Use Al cambiar el estado para observar la variable compartida.
  3. Cuando se desencadena el evento On State Changed (porque la variable compartida cambió su valor), aplique cualquier cambio local que desee (por ejemplo, actualice el color del skybox).

De este modo, el estado local (el color del skybox) sigue el estado compartido (el estado del modificador). Lo bueno de esto es que funciona sin cambios para el cliente local que voltea el conmutador, para todos los demás clientes remotos que están presentes en la sala al mismo tiempo, y para los clientes futuros que se unirán a la sala más adelante.

Hacer que el estado local siga el estado compartido: Procedimientos recomendados

Eventos locales: por ejemplo, un nodo de evento On State Changed que observa la propiedad Is Selected Locally de un componente Mesh Interactable Body :

  • 🆗 Puede cambiar el estado local que es privado a un cliente. Estos cambios de estado permanecerán estrictamente en el cliente local y desaparecerán cuando el cliente salga de la sesión.
  • 🆗 Puede cambiar el estado compartido.
  • No se puede cambiar el estado local para que sea coherente entre los clientes. Un evento local solo se ejecuta en un cliente, por lo que las actualizaciones necesarias para mantener el estado local coherente entre los clientes simplemente no se producirán en ningún otro cliente.

Eventos compartidos: por ejemplo, un nodo de evento On Trigger Enter asociado a un colisionador de desencadenador físico compartido:

  • 🆗 Puede cambiar el estado local de los efectos momentáneos: por ejemplo, un efecto de partícula o un efecto de audio corto. Solo los clientes presentes en la sala cuando se produzca el evento compartido podrán ver el efecto local; los clientes que se unan a la sala más adelante no lo harán.
  • No se puede cambiar el estado local para que sea coherente entre los clientes. Un evento compartido solo se ejecuta en los clientes que están presentes en el momento en que se produce, pero no se reproducirá para los clientes que se unan a la sesión más adelante.
  • No debe cambiar el estado compartido. Puesto que un evento compartido se ejecuta en todos los clientes, todos los clientes lo hacen muy cerca en el tiempo. Dependiendo de la naturaleza del cambio, podría terminar repitiendo varias veces (por ejemplo, un contador de puntuación podría incrementarse en más de uno en respuesta a un único evento).

En los eventos State Changed que observan el estado compartido en variables compartidas o propiedades de componentes compartidos:

  • 🆗 Puede cambiar el estado local para que sea coherente con el estado compartido entre los clientes. Para que esto funcione bien de forma repetible y coherente para todos los clientes, debe traducir todos los valores nuevos posibles del estado compartido observado en estado local, no solo unas pocas transiciones de estado seleccionados como cereza (como Está seleccionado en true).

Hacer que el estado local siga el estado compartido: ejemplo

En este ejemplo, hay dos botones interactivos en este entorno: uno etiquetado con "Star", el otro etiquetado con "Sponge". La selección de cualquiera de los botones se supone que debe hacer dos cosas:

  • Almacene la etiqueta correspondiente en una variable de cadena compartida denominada ObjectKind.
  • Almacene la referencia a un objeto de escena correspondiente en una variable de referencia gameObject local denominada ObjectRef.

Estos son los dos flujos de script, uno para cada botón. Cada escucha la propiedad Is Selected compartida del componente Mesh Interactable Body de un botón y actualiza ObjectKind y ObjectRef en función del botón seleccionado:

______________

Todo parece funcionar bien, pero solo para los usuarios que ya están en la sala cuando se selecciona uno de los botones. Cualquier usuario que se una a la sesión encuentra más adelante un estado incoherente en su versión local del entorno compartido: Solo ObjectKind se establece correctamente según el botón seleccionado más recientemente, pero ObjectRef sigue siendo NULL.

¿Qué ocurre con estos dos flujos de script?

En primer lugar, tenga en cuenta que estos flujos de script se desencadenan mediante un evento compartido porque ambos escuchan el uso compartido de cada botón Es la propiedad Selected que cambia. Esto parece tener sentido porque es la única manera de actualizar la variable ObjectRef local en todos los clientes.

Pero:

  • Los eventos compartidos no deben cambiar el estado compartido, pero estos flujos de script actualizan la variable ObjectKind compartida.
  • Los eventos compartidos no pueden cambiar el estado local para ser coherentes entre los clientes, pero estos flujos de script actualizan la variable ObjectRef local, que pretendemos ser coherentes en todos los clientes, al igual que ObjectKind.

Por lo tanto, la forma en que se configura actualmente, en realidad no deberíamos hacer ninguna de las cosas que necesitamos que hagan los botones.

La única manera obvia de salir de este problema es hacer que los eventos que desencadenan estos flujos sean locales. Podemos hacerlo haciendo que el nodo de evento On State Changed observe la propiedad Is Selected Locally en lugar de Is Selected.

Con el evento ahora siendo local, esto significa...

  • Los eventos locales pueden cambiar el estado compartido para que ahora podamos actualizar de forma segura la variable ObjectKind compartida y su valor se compartirá automáticamente entre los clientes mediante las redes integradas de Mesh Visual Scripting.
  • Los eventos locales no pueden cambiar el estado local para que sea coherente entre los clientes, por lo que todavía no se puede actualizar la variable ObjectRef local en estos flujos de script. Tendremos que encontrar otra manera.

Así es como se ven los dos flujos de script después de estos cambios:

______________

¿Qué podemos hacer para establecer la variable ObjectRef local para que sea coherente con esto? Afortunadamente, estos dos flujos de script ya establecen algún estado compartido que podríamos seguir: la variable Shared ObjectKind . Todo lo que tenemos que hacer es usar un evento On State Changed que observe esta variable y actualice la variable ObjectRef local en función de su valor:

______________

Se trata de una manera correcta de hacerlo porque los eventos On State Changed que observan el estado compartido pueden cambiar el estado local para que sea coherente con él. Esto funcionará para el cliente que presionó el botón, para todos los demás clientes presentes en la misma sala al mismo tiempo, y para todos los clientes que se unirán a la sesión más adelante.

Problemas de redes

Actualizaciones compartidas de alta frecuencia

Casi todo el estado de la escena lo comparte Mesh Visual Scripting de forma predeterminada. Eso es ideal para compartir, pero también puede colarse por accidente y causar una carga de red innecesaria. Por ejemplo, el siguiente flujo de script inundará la red con actualizaciones redundantes en la rotación de la transformación. Sin embargo, dado que todos los clientes lo están ejecutando al mismo tiempo, ninguna de las actualizaciones remotas tendrá un impacto real en cualquier cliente localmente:

______________

En este caso, probablemente debe usar un ámbito de script local para convertir el componente de transformación en cada cliente. Además, probablemente debería usar un componente Animator en lugar de un flujo de script al actualizar para empezar.

El panel Diagnóstico de scripting visual mesh y contenido Analizador de rendimiento (CPA), a partir de Mesh Toolkit 5.2411, muestra una advertencia de "actualización compartida de alta frecuencia" para este tipo de construcción.

En Start se ejecuta en cada cliente

Es posible que tenga la tentación de pensar en el evento On Start como algo que se ejecuta en el inicio de la sesión, pero realmente se desencadena en cada cliente, localmente, cuando se unen a la sesión. Es perfectamente adecuado para inicializar el estado local:

______________

Sin embargo, cuando intente usar Al iniciar para inicializar el estado compartido, verá que el estado compartido se volverá a inicializar involuntariamente para todos cuando alguien se una a la sesión:

______________

El panel Mesh Visual Scripting Diagnostics (as of Mesh Toolkit 5.2410) y Content Analizador de rendimiento (CPA) (as of Mesh Toolkit 5.2411) muestra una advertencia "Actualización compartida en la unión a la sesión" cuando detectan esto.

El uso compartido está escrito, pero la asignación de variables no es

Por motivos de seguridad y seguridad, las variables de script visual compartido están fuertemente tipadas. Esto significa que el tipo que seleccione en el componente Variables para las variables de script que ha declarado define qué tipo de valor exacto se sincronizará entre los clientes.

Desafortunadamente, Unity Visual Scripting omite completamente el tipo declarado de una variable al actualizar su valor. Por ejemplo, es fácil almacenar accidentalmente un valor con tipo Float en una variable declarada para el tipo Integer. Dentro del cliente local, los scripts visuales no observarán este error porque Visual Scripting convertirá automáticamente el float erróneo en el entero esperado cuando sea necesario. Sin embargo, cuando se trata de sincronizar este valor entre clientes, Mesh Visual Scripting no puede tomar las mismas libertades: La garantía de "coherencia final" impide cualquier conversión de valor en curso, y las consideraciones de seguridad y seguridad hacen que no se pueda aceptar un tipo de valor diferente de un cliente remoto que lo declarado para la variable.

Por ejemplo, considere esta declaración de una variable compartida denominada MyIntegerVar:

______________

Este es un flujo de script que actualiza esta variable:

______________

¿Qué podría salir mal? Desafortunadamente, el nodo de script Random | Range usado en este ejemplo incluye dos tipos: uno que genera un valor entero aleatorio y otro que genera un valor Float aleatorio. La diferencia entre esos dos nodos de script en el panel selector de nodos es sutil:

______________

Por lo tanto, si selecciona accidentalmente el nodo de script de intervalo aleatorio | incorrecto allí, es posible que el script termine almacenando involuntariamente un valor Float en la variable de tipo Entero, pero ese valor Float erróneo no se replicará en ningún otro cliente.

Tenga esto en cuenta como una posible razón por la que una variable compartida que ha creado puede parecer haber dejado de compartirse. Las futuras versiones de Mesh Visual Scripting pueden advertir de este tipo de error de script cuando puedan detectarlo.

Pasos siguientes