Con Verse, puedes crear tus propios componentes y añadirlos a tus entidades. Con los Componentes personalizados de Verse, puedes generar y eliminar entidades de la escena, añadir o eliminar Componentes de las entidades, crear tus propios comportamientos, como una entidad que desaparece en un loop o lo que se te ocurra.
Cómo crear un componente de Verse nuevo
Puedes crear un componente de Verse nuevo desde el archivo de plantilla de Verse.
Para crear un componente de Verse nuevo:
En el panel de detalles de la entidad, elige Añadir componente > Nuevo componente de Verse.
También puedes crear un componente de Verse nuevo si añades un archivo de Verse nuevo a través del explorador de Verse.
En la lista de plantillas de código de Verse, elige Componente de Scene Graph.
Establece el nombre del componente que creaste con Verse en Nombre de componente. En este ejemplo, el componente se llama
my_verse_component.Haz clic en Crear para crear el archivo de componente de Verse. El componente que creaste con Verse ahora aparece en la lista de componentes cuando eliges añadir un componente a la entidad.
Solo puedes añadir uno de una clase o subclase de componente dada. Por ejemplo, solo puedes tener un mesh_component en una entidad. Esto se extiende a las subclases de componentes, es decir, si añades un capsule_light_component a tu entidad, no puedes añadir también un rect_light_component, ya que ambos son subclases de light_component. Aplica la misma limitante a tus componentes personalizados creados con Verse.
Tiempo de vida de los componentes
Los componentes atraviesan una serie de funciones de tiempo de vida, ya que se añaden a entidades, a la escena y luego se ejecutan en la simulación. Tus componentes creados con Verse deberían anular esos métodos para establecerse y ejecutar su simulación.
Conforme se desactive un componente, atravesará la versión de desactivación de dichas funciones, lo que te da la oportunidad de despejar cualquier estado retenido en el componente antes de desecharlo.
A continuación, una lista de los estados de tiempo de vida de un componente:
Iniciado
AddedToScene
BeginSimulation
EndSimulation
RemovingFromScene
Desinicializando
Las funciones de tiempo de vida de los componentes son distintas de los tiempos de vida de los dispositivos. La lógica los componentes se ejecuta tanto en modo de edición como en modo de juego. Cualquier comportamiento que agregues se ejecutará de inmediato cuando comiences tu sesión. Si quieres que la lógica de tu componente solo se ejecute al comenzar el juego, puedes generar prefabricados en la función OnBegin() de un dispositivo de Verse.
Cómo consultar sobre entidades y componentes con Verse
Hay numerosas maneras de buscar entidades y componentes en el código de Verse. El modo en que estructuras las entidades y los componentes influye en la forma de consultar y desarrollar funcionalidad en el código de Verse.
Para consultar entidades y Componentes en Verse, debes comenzar con una entidad y return las entidades anidadas por encima o por debajo de ella en la jerarquía. Puedes consultar por el elemento base o derivado directo de una entidad, y también por todas sus entidades ancestro y descendiente.
Obtener entidades con tipo de componente
Si deseas buscar todas las entidades que tienen un componente de un tipo específico, llama a la entidad que deseas consultar. Si la entidad que consultas es la entidad de simulación, devolverá todas las entidades que tengan componentes de ese tipo en la escena.
En el siguiente ejemplo, el componente de Verse obtiene todas las entidades que tienen asociado el componente light_component. Para cada entidad que encuentra, genera un particle_system_component y se lo adjunta. Aquí, BlowingParticles es un emisor Niagara al que se hace referencia en el archivo Assets.digest.Verse.
El light_component es una superclase para todos los diferentes tipos de componentes de luz que puedes añadir a tus entidades. En la consulta que aparece a continuación, LightComponent se utiliza para encontrar entidades con cualquier tipo de componente de luz en ellas.
# Runs when the component should start simulating in a running game.
OnBeginSimulation<override>():void =
# Run OnBeginSimulation from the parent class before
# running this component's OnBeginSimulation logic
(super:)OnBeginSimulation()
for:
LightComponent : Entity.GetSimulationEntity[].FindDescendantEntitiesWithComponent(light_component)
do:
# Create a particle system component and add it to the entity.
En el siguiente ejemplo, se muestra cómo consultar por todas las entidades que tienen sistemas de partículas anidados en la entidad a la que está asociado el componente de Verse mediante la función FindDescendantEntitiesWithComponent(). De la misma manera, también puedes obtener todas las entidades ancestro con un componente en particular usando FindAncestorEntitiesWithComponent().
# Runs when the component should start simulating in a running game.
# Can be suspended throughout the lifetime of the component. Suspensions
# will be automatically canceled when the component is disposed or the
# game ends.
OnSimulate<override>()<suspends>:void=
# Get all entities that have particle system components nested under the entity this component is attached to.
ParticleSystemEntities := Entity.FindDescendantEntitiesWithComponent(particle_system_component)
# Get all entities with particle system components that are ancestors of this entity.
Si necesitas consultar todas las entidades en toda la escena, puedes hacerlo tras obtener la entidad de simulación y ejecutar las consultas. Esto empieza en la cima de la estructura de la entidad y busca todas las entidades anidadas que coinciden con la consulta. Para acceder a la entidad de simulación, llama a la función falible GetSimulationEntity[] en la entidad a la que está asociado el componente de Verse.
# Runs when the component should start simulating in a running game.
# Can be suspended throughout the lifetime of the component. Suspensions
# will be automatically canceled when the component is disposed or the
# game ends.
OnSimulate<override>()<suspends>:void=
# Get the simulation entity.
if:
SimulationEntity := Entity.GetSimulationEntity[]
then:
Hacer que el componente de Verse recorra el árbol de entidades de arriba a abajo constantemente puede ser costoso. Si tu comportamiento depende de una estructura de entidades específica, cualquier cambio sutil en la estructura de entidades puede hacer que tu comportamiento cambie de forma involuntaria o que no funcione en absoluto.
Por el otro lado, esto también significa que el componente puede requerir menos configuración porque todo lo que tienes que hacer es agregar el componente de Verse y tener la estructura de entidades correcta. Ten en cuenta estas compensaciones a medida que creas las entidades y desarrollas la lógica del componente de Verse.
Explora el módulo SceneGraph para conocer todas las maneras de trabajar con entidades y componentes en Verse. A continuación, se describen algunas formas comunes de consultar entidades y componentes en el código.
Obtener los componentes de una entidad
Puedes usar Verse para obtener un componente de un tipo específico en una entidad si llamas a GetComponent[]. Esto es útil para crear lógica personalizada que depende del comportamiento de otros componentes. Por ejemplo, usar sound_component para reproducir audio según el color de una luz u obtener un particle_system_component para aplicar efectos en función de si la entidad está dentro de una zona determinada.
En el siguiente ejemplo, el componente de Verse hace que una plataforma aparezca y desaparezca repetidamente en un bucle. Para hacerlo, obtiene el componente de malla en la entidad y lo deshabilita, luego lo vuelve a habilitar después de una duración definida.
using { /Verse.org }
using { /Verse.org/Native }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SceneGraph }
# A Verse-authored component that can be added to entities.
# This component will make the entity appear and disappear on loop.
disappear_on_loop_component := class<final_super>(component):
# How long in seconds the entity should be hidden.
@editable
En otro ejemplo, el componente de Verse obtiene el light_component en la entidad y cambia su color a naranja oscuro. El light_component es una superclase de todos los tipos de luces que puedes añadir a las entidades, por lo que en este ejemplo se encuentra cualquier componente que sea una subclase de ella.
# Runs when the component should start simulating in a running game.
# Can be suspended throughout the lifetime of the component. Suspensions
# will be automatically canceled when the component is disposed or the
# game ends.
OnSimulate<override>()<suspends>:void=
# Find any component on this entity that subclasses from light_component.
if:
LightComponent := Entity.GetComponent[light_component]
then:
Cómo obtener todos los componentes
Puedes usar la función GetComponents() para devolver todos los componentes de la entidad. Dado que el código no sabe qué tipo de componentes son, puedes utilizar la conversión para realizar diferentes operaciones según el tipo de cada componente. En el siguiente ejemplo, se obtiene una matriz de todos los componentes de una entidad y se intenta convertirlos al tipo enable. Si la conversión tiene éxito, el componente implementa la interfaz enable. Luego, deshabilita cada componente que implementa esta interfaz.
# Runs when the component should start simulating in a running game.
# Can be suspended throughout the lifetime of the component. Suspensions
# will be automatically canceled when the component is disposed or the
# game ends.
OnSimulate<override>()<suspends>:void=
# Get a list of all components on the entity.
ComponentList := Entity.GetComponents()
for:
Component:ComponentList
Buscar entidades por etiquetas de juego
Puedes añadir un componente de etiqueta a las entidades para poder encontrar entidades específicas dentro de la escena de manera similar a la forma en que añades etiquetas de juego a los actores. Esto es útil para elegir con qué entidades quieres trabajar en lugar de depender de cosas que se pueden cambiar, como qué componentes tienen o en qué parte de la escena se encuentran.
Esto se debe a que depender de las cosas cambiables puede provocar un comportamiento no deseado en el juego a medida que cambias y añades entidades nuevas al proyecto. Puedes añadir etiquetas en el editor mediante la adición de un tag_component a la entidad y la selección de etiquetas en el menú desplegable Etiquetas o, en código de Verse, mediante la función AddTag().
En el siguiente ejemplo, se consulta a la entidad de simulación todos los descendientes marcados con la etiqueta my_tag en su tag_component.
# Runs when the component should start simulating in a running game.
# Can be suspended throughout the lifetime of the component. Suspensions
# will be automatically cancelled when the component is disposed or the
# game ends.
OnSimulate<override>()<suspends>:void =
# Get the simulation entity.
if:
SimulationEntity := Entity.GetSimulationEntity[]
then:
Buscar entidades con superposiciones
Los volúmenes de colisión son volúmenes que representan las formas de colisión de las mallas. Puedes usarlos para consultar si hay objetos superpuestos dentro de una forma particular, como dañar objetos si se acercan demasiado a una torre o detectar cuando un balón de fútbol entra en una portería. En Verse, puedes usar la función FindOverlapHits() para buscar todas las entidades dentro de un área en particular.
Esta área puede ser la propia entidad, un volumen de colisión determinado, como una esfera o una caja, o una posición desde la que simular la entidad. Luego, devuelve una lista de overlap_hit. Cada overlap_hit te brinda información sobre el componente o volumen superpuesto por el volumen de origen, y puedes consultar estos componentes para encontrar su entidad asociada.
En el siguiente ejemplo, se crea una esfera con un radio de 256.0 unidades centrada en la transformación de la entidad. Luego, encuentra todas las superposiciones dentro de la esfera y devuelve una lista de overlap_hit. Dado que cada overlap_hit es un componente o un volumen, puedes consultar tanto TargetComponent como TargetVolume para saber de qué tipo es. Si overlap_hit es un componente, el código obtiene la entidad del componente. Por último, comprueba si la entidad tiene un componente de luz. Si es así, cambia el color de la luz a azul. Con un volumen lo suficientemente grande, ¡cambiarás el color de cada luz en tu isla con solo unas pocas líneas de código!
# Runs when the component should start simulating in a running game.
# Can be suspended throughout the lifetime of the component. Suspensions
# will be automatically canceled when the component is disposed or the
# game ends.
OnSimulate<override>()<suspends>:void=
# Define a volume to find entities within.
# This is a sphere whose radius is 256.
CollisionSphere:collision_sphere = collision_sphere:
Radius := 256.0
Este código simula un volumen de collision_sphere superpuesto denotado por el círculo con un radio de 256.0 unidades centrado en la entidad de cubo, que devuelve cualquier componente o volumen con el que se superponga la esfera. A continuación, obtiene la entidad base de cada componente superpuesto y vuelve azules todos los componentes de luz que tenga. Debido a que el cubo está dentro de collision_sphere cuando comienza la superposición, se incluirá en la lista de overlap_hits y también se volverá azul. Ten en cuenta que la entidad de cono rojo más a la derecha está fuera de collision_sphere, por lo que no se superpondrá y se volverá azul.
Buscar entidades con barridos
Otra forma importante de consultar entidades es a través de barridos. El barrido se refiere a mover un objeto sobre una distancia definida a lo largo de un vector particular. Por ejemplo, mover un bloque a través de una plataforma para empujar a los jugadores hacia un hueco o lanzar un misil hacia adelante para destruir una pared.
En Verse, puedes simular barridos para consultar colisiones entre objetos mediante la función FindSweepHits(). Esta función toma un vector de desplazamiento para simular el barrido de un objeto. Puedes realizar barridos con la entidad base o con un volumen de colisión dado y especificar la transformación global inicial desde la que comenzar el barrido.
La función FindSweepHits() devuelve una lista de sweep_hit. Cada sweep_hit ofrece la misma información que un overlap_hit, como el componente o volumen tocado, y el volumen o componente de origen que realiza el barrido. También proporciona información sobre la posición del contacto, la normal, la normal de la cara y la distancia a lo largo del barrido donde ocurrió el impacto.
En el siguiente ejemplo, se toma una Entidad y se llama a FindSweepHit(), y se pasa un vector con una longitud de 1000.0 para el valor Forward. Luego, el código simula qué colisiones ocurrirían si la Entidad se moviera 1000.0 unidades en la dirección positiva de avance y devuelve una lista de sweep_hit.
Dado que cada sweep_hit es un componente o un volumen, puedes consultar tanto TargetComponent como TargetVolume para saber de qué tipo es. Si el impactado es un componente, el código obtiene la entidad base del componente. Por último, comprueba si la entidad tiene un componente de luz. Si es así, cambia el color de la luz a azul.
for:
# Simulate sweeping this entity 1000 units in the positive X direction, and return any components and volumes it overlaps with.
SweepHit : Entity.FindSweepHits(vector3{Left := 0.0, Up := 0.0, Forward := 1000.0}, Entity.GetGlobalTransform(), CollisionBox)
# Check that the overlap is a component, and if so get its parent entity.
# Then if the entity has a light component, change its color filter.
TargetComponent := SweepHit.TargetComponent
TargetEntity := TargetComponent.Entity
LightComponent := TargetEntity.GetComponent[light_component]
do:
Este código simula el barrido de la entidad cúbica a 1000.0 unidades en la dirección X positiva, lo que devuelve cualquier componente con el que se superponga. A continuación, obtiene la entidad base del componente superpuesto y convierte en azules todos los componentes de luz que tenga. Ten en cuenta que la lista de aciertos no incluye a la entidad que realiza el barrido, por lo que el cubo en sí no se volverá azul. La entidad de cono rojo más a la derecha tampoco se volverá azul, ya que está fuera del barrido.
El siguiente ejemplo es similar al anterior, excepto que primero construye un volumen collision_box y luego lo usa para hacer un barrido de 1000.0 unidades en la dirección Forward positiva, comenzando desde el centro de la entidad del cubo. Como el cubo está dentro de la collision_box cuando comienza el barrido, se incluirá en la lista de sweep_hits y también se volverá azul.
# Define a volume to sweep over entities.
# This box is 1/4th the size of a standard 512x512 grid tile.
CollisionBox:collision_box = collision_box:
Extents := vector3:
Left := 128.0,
Up := 128.0,
Forward := 128.0
for:
# Simulate sweeping the CollisionBox 1000 units in the positive X direction, and return any components and volumes it overlaps with.
SweepHit : Entity.FindSweepHits(vector3{Left := 0.0, Up := 0.0, Forward := 1000.0}, Entity.GetGlobalTransform(), CollisionBox)
Este código simula el barrido de un volumen collision_box indicado por el cuadrado amarillo 1000.0 unidades en la dirección directa positiva, y devuelve cualquier componente con el que se superponga. A continuación, obtiene la entidad base del componente superpuesto y convierte en azules todos los componentes de luz que tenga. Como el cubo está dentro de collision_box cuando comienza el barrido, se incluirá en la lista de sweep_hits y se volverá azul. La entidad de cono rojo más a la derecha no se volverá azul ya que está fuera del barrido.
Cómo generar y eliminar entidades con Verse
Si deseas eliminar una entidad de la escena, llama a RemoveFromParent() en la entidad. Si deseas añadir una entidad (nueva o eliminada anteriormente) a la escena, llama a AddEntities() en la entidad que se convierte en la entidad base.
En el siguiente ejemplo, el componente de Verse busca todas las entidades etiquetadas con la etiqueta de juego my_tag. Elimina cada entidad encontrada de su base, lo que elimina la entidad de la escena y vuelve a añadir la misma entidad a su base después de cinco segundos para volver a generarla en la escena.
# Runs when the component should start simulating in a running game.
# Can be suspended throughout the lifetime of the component. Suspensions
# will be automatically cancelled when the component is disposed or the
# game ends.
OnSimulate<override>()<suspends>:void =
# Find all entities tagged and get their parent entity.
for:
TaggedEntity : Entity.GetSimulationEntity[].FindDescendantEntitiesWithTag(my_tag{})
Parent := TaggedEntity.GetParent[]
Del mismo modo, puedes añadir componentes a una entidad si llamas a AddComponents() y pasas la lista de componentes que quieres añadir. También puedes eliminar una entidad llamando a RemoveFromParent() en la entidad, y puedes eliminar un componente de una entidad llamando a RemoveFromEntity() en el componente. Las entidades y los componentes eliminados pueden volver a añadirse a la escena con AddEntities() y AddComponents() respectivamente. Ten en cuenta que no puedes cambiar la entidad base de los componentes eliminados que vuelves a añadir a la escena.
Prefabricados
Los prefabricados que creas en tu proyecto se exponen como una clase a Verse en el archivo Assets.digest.Verse de tu proyecto. Las entidades y los componentes definidos en tu prefabricado son accesibles en Verse mediante las llamadas a GetEntities() y GetComponents() en un prefabricado.
Para generar instancias de tus prefabricados, puedes instanciar la clase del prefabricado y añadir los prefabricados a una entidad de la escena. En el siguiente ejemplo, el componente de Verse crea en el editor una instancia del prefabricado, denominada loop_disappearing_platform_prefab, y la añade a la escena.
# Runs when the component should start simulating in a running game.
# Can be suspended throughout the lifetime of the component. Suspensions
# will be automatically cancelled when the component is disposed or the
# game ends.
OnSimulate<override>()<suspends>:void =
if:
SimulationEntity := Entity.GetSimulationEntity[]
then:
# Create an instance of the disappearing on loop platform from its prefab.
DisappearingPlatform:disappearing_platform_prefab = disappearing_platform_prefab{}
Prácticas recomendadas y sugerencias
Al crear tus propios componentes en Verse, ten presente las siguientes prácticas recomendadas y sugerencias:
Por lo general, los componentes de Verse que dependen de otros componentes deben estar en la misma entidad.
Los componentes exponen eventos de tic previos y posteriores a las simulaciones físicas, que ocurren en cada fotograma. Esto es útil si necesitas realizar cierta lógica antes de aplicar la física, como modificar la transformación, y después, por ejemplo, leer las posiciones de los objetos después de la física.
Si no necesitas específicamente eventos previos y posteriores a la aplicación de la física, debes continuar usando las expresiones de concurrencia de Verse para controlar el flujo del tiempo de acuerdo con una lógica determinada. Para obtener más detalles, consulta Flujo de tiempo y concurrencia.
Las funciones de tiempo de vida de los componentes son distintas de los tiempos de vida de los dispositivos. La lógica los componentes se ejecuta tanto en modo de edición como en modo de juego. Si quieres que la lógica de tu componente solo se ejecute al comenzar el juego, puedes generar prefabricados en la función
OnBegin()de un dispositivo de Verse.