Puedes crear tus propios componentes utilizando Verse para 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 bucle o lo que se te ocurra.
Cómo crear un nuevo componente de Verse
Puedes crear un nuevo componente de Verse a partir del archivo de plantilla de Verse.
Para crear un nuevo componente de Verse:
En el panel Detalles de tu entidad, elige Añadir componente > Nuevo componente de Verse.
También puedes crear un nuevo componente de Verse añadiendo un nuevo archivo de Verse a través del explorador de Verse.
En la lista de plantillas de código de Verse, elige Componente de Scene Graph.
Establece Nombre del componente con el nombre de tu componente creado con Verse. En este ejemplo, el componente se llama
my_verse_component.Haz clic en Crear para crear tu archivo del componente de Verse. Tu componente creado con Verse aparece ahora en la lista de componentes cuando decides añadir un componente a tu entidad.
Solo puedes añadir una clase o subclase de componente determinada. Por ejemplo, solo puedes tener un mesh_component en una entidad. Esto se extiende a las subclases de componentes, lo que significa que si añades un capsule_light_component a tu entidad, no puedes añadir también un rect_light_component, ya que ambas son subclases de light_component. La misma limitación se aplica a los componentes personalizados creados en Verse.
Duración del componente
Los componentes pasan por una serie de funciones de tiempo de vida a medida que se añaden a las entidades, se añaden a la escena y comienzan a ejecutarse en la simulación. Los componentes creados con Verse deben anular estos métodos para configurar y ejecutar su simulación.
Cuando un componente se apaga, se mueve a través de la versión de apagado de estas funciones, lo cual te da la oportunidad de limpiar cualquier estado retenido en el componente antes de que se elimine.
A continuación se indican los estados de vida útil de un componente:
Initialized
AddedToScene
BeginSimulation
EndSimulation
RemovingFromScene
Uninitializing
Las funciones de duración de los componentes son diferentes de la duración de los dispositivos. La lógica de los componentes funciona tanto en el modo de edición como en el de juego. Cualquier comportamiento que añadas se ejecutará inmediatamente al abrir la sesión. Si quieres que la lógica de tu componente solo se ejecute cuando se inicie el juego, puedes generar prefabricados en la función OnBegin() de un dispositivo Verse.
Cómo consultar entidades y componentes con Verse
Hay múltiples formas de encontrar entidades y componentes en tu código Verse. La forma en que estructuras tus entidades y componentes afecta a la forma en que consultas y desarrollas la funcionalidad en tu código Verse.
La consulta de entidades y componentes en Verse requiere que empieces por una entidad y devuelvas las entidades anidadas por encima o por debajo de ella en la jerarquía. Puedes consultar el padre o los hijos directos de una entidad, así como todas sus entidades ancestros y descendientes.
Obtener entidades con tipo de componente
Puedes encontrar todas las entidades que tienen un componente de un tipo específico si llamas a la entidad que quieres consultar. Si la entidad que consultas es la entidad de simulación, devuelve todas las entidades que tienen componentes de ese tipo en la escena.
En el siguiente ejemplo, el componente de Verse obtiene todas las entidades que tienen adjunto el componente light_component. Para cada una de las entidades que encuentra, genera un particle_system_component y se lo une a ellas. Aquí, BlowingParticles es un emisor de Niagara al que se hace referencia en el archivo Assets.digest.Verse.
light_component es una superclase para todos los distintos tipos de componentes de luz que puedes añadir a las entidades. En la consulta siguiente, 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.
El siguiente ejemplo muestra cómo consultar todas las entidades que tienen sistemas de partículas anidados bajo la entidad a la que está unido el componente de Verse mediante la función FindDescendantEntitiesWithComponent(). Del mismo modo, también puedes obtener todas las entidades ancestros con un componente concreto mediante 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 entidades en toda tu escena, puedes hacerlo al obtener la entidad de simulación y realizar tus consultas en ella. Empieza en la parte superior de la estructura de entidades y busca todas las entidades anidadas que coincidan 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á unido 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 tu componente de Verse busque constantemente arriba y abajo en el árbol de entidades puede tener un gran coste. Si tu comportamiento depende de una estructura de entidad específica, cualquier cambio sutil en tu estructura de entidad puede hacer que tu comportamiento cambie de forma no intencionada o que no funcione en absoluto.
Por otra parte, esto también significa que tu componente puede requerir menos configuración, porque todo lo que tienes que hacer es añadir tu componente de Verse y tener la estructura de entidades correcta. Ten en cuenta estas ventajas y desventajas cuando crees tus entidades y desarrolles la lógica de tu componente de Verse.
Explora el módulo SceneGraph para conocer todas las formas de trabajar con entidades y componentes en Verse. A continuación se describen algunas formas habituales de consultar entidades y componentes en tu código.
Obtener componentes de una entidad
Puedes utilizar Verse para obtener un componente de un tipo específico en una entidad al llamar a GetComponent[]. Esto resulta útil para crear una lógica personalizada que dependa del comportamiento de otros componentes. Por ejemplo, utilizar el sound_component para reproducir audio en función del color de una luz u obtener un particle_system_component para aplicar efectos en función de si la entidad se encuentra dentro de una zona determinada.
En el siguiente ejemplo, el componente Verse hace aparecer y desaparecer una plataforma en un bucle. Para ello, obtiene el componente de malla de la entidad, lo desactiva y lo vuelve a activar tras una duración determinada.
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 light_component en la entidad y cambia su color a naranja oscuro. light_component es una superclase para todos los tipos de luces que puedes añadir a tus entidades, por lo que este ejemplo encuentra cualquier componente que sea subclase de la misma.
# 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 utilizar la función GetComponents() para devolver todos los componentes de la entidad. Como tu código desconoce qué tipo de componentes son, puedes utilizar el casting para realizar diferentes operaciones en función del tipo de cada componente. El siguiente ejemplo obtiene una matriz de todos los componentes de una entidad e intenta convertirlos al tipo enableable. Si la conversión se realiza correctamente, el componente implementa la interfaz enableable. A continuación, desactiva todos los componentes que implementan 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
Cómo buscar entidades por etiquetas de juego
Puedes añadir un componente de etiqueta a tus entidades para poder encontrar entidades específicas dentro de tu escena de forma similar a como puedes añadir etiquetas de jugabilidad a tus actores. Esto es útil para elegir con qué entidades quieres trabajar en lugar de depender de cosas cambiantes, como qué componentes tienen o dónde están en la escena.
Esto se debe a que depender de cosas modificables puede causar un comportamiento no deseado en tu juego a medida que cambias y añades nuevas entidades a tu proyecto. Puedes añadir etiquetas en el editor al añadir un tag_component a la entidad y seleccionar etiquetas en el desplegable Etiquetas, o en código de Verse mediante la función AddTag().
El siguiente ejemplo consulta a la entidad de simulación todos los descendientes que están 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:
Cómo buscar entidades con superposiciones
Los volúmenes de colisión son volúmenes que representan las formas de colisión de las mallas. Puedes utilizarlos para consultar si hay objetos superpuestos dentro de una forma concreta, como dañar objetos si se acercan demasiado a una torre o detectar cuándo un balón de fútbol entra en una portería. En Verse, puedes utilizar la función FindOverlapHits() para encontrar todas las entidades dentro de un área concreta.
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. A continuación, devuelve una lista de overlap_hit. Cada overlap_hit te proporciona información sobre el componente o volumen solapado por el volumen de origen, y puedes consultar estos componentes para encontrar su entidad asociada.
El siguiente ejemplo crea una esfera con un radio de 256.0 unidades centrada en la transformación de la entidad. A continuación, encuentra todas las superposiciones dentro de la esfera y devuelve una lista de overlap_hit. Como cada overlap_hit es un componente o un volumen, puedes consultar tanto el TargetComponent como el 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. Si el volumen es lo suficientemente grande, cambiarás el color de cada luz de 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 indicado por el círculo con un radio de 256.0 unidades centrado en la entidad del cubo, y devuelve cualquier componente o volumen con el que se solape la esfera. A continuación, obtiene la entidad padre de cada componente superpuesto y convierte en azules los componentes de luz que tenga. Como 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 situada más a la derecha está fuera de `collision_sphere`, por lo que no se solapará y se volverá azul.
Cómo buscar entidades con barridos
Otra forma importante de consultar entidades es mediante barridos. El barrido se refiere a mover un objeto a lo largo de una distancia determinada por un vector concreto. Por ejemplo, mover un bloque a través de una plataforma para empujar a los jugadores a un hueco o lanzar un misil hacia delante para destruir un muro.
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 padre o con un volumen de colisión determinado y especificar la transformación global inicial desde la que empezar a barrer.
La función FindSweepHits() devuelve una lista de sweep_hit. Cada sweep_hit te da la misma información que un overlap_hit, como el componente o volumen visitado, y el volumen o componente fuente que realiza el barrido. También proporciona información sobre la posición de contacto, la normal, la normal de cara y la distancia a lo largo del barrido donde se ha producido la coincidencia.
El siguiente ejemplo toma una entidad, llama a FindSweepHit() y pasa un vector con una longitud de 1000.0 para el valor Adelante. A continuación, el código simula las colisiones que se producirían si la entidad se moviera 1000.0 unidades en la dirección positiva Adelante y devuelve una lista de sweep_hit.
Como cada sweep_hit es un componente o un volumen, puedes consultar tanto el TargetComponent como el TargetVolume para saber de qué tipo es. Si es un componente, el código obtiene la entidad padre 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 1000.0 unidades de la entidad cúbica en la dirección positiva X, y devuelve cualquier componente con el que se solape. A continuación, obtiene la entidad padre del componente superpuesto y convierte en azules los componentes de luz que tenga. Ten en cuenta que la lista de superposiciones 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 situada 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, a continuación, lo utiliza para barrer 1000.0 unidades en la dirección positiva Adelante, empezando desde el centro de la entidad cúbica. 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 positiva Adelante, y devuelve cualquier componente con el que se solape. A continuación, obtiene la entidad padre del componente superpuesto y convierte en azules los componentes de luz que tenga. Como el cubo está dentro de la `collision_box` cuando comienza el barrido, se incluirá en la lista de `sweep_hits` y se volverá azul. La entidad de cono rojo situada más a la derecha no se volverá azul, ya que está fuera del barrido.
Generación y eliminación de entidades con Verse
Puedes eliminar una entidad de la escena llamando a RemoveFromParent() en la entidad. Puedes añadir una entidad a la escena, ya sea nueva o eliminada previamente, llamando a AddEntities() en la entidad que se convierte en la entidad principal.
En el siguiente ejemplo, el componente de Verse encuentra todas las entidades etiquetadas con la etiqueta de jugabilidad my_tag. Elimina cada entidad encontrada de su padre, que elimina la entidad de la escena y vuelve a añadir la misma entidad a su principal al cabo de cinco segundos para que vuelva a aparecer 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 al llamar a AddComponents() y pasar la lista de componentes que quieres añadir. También puedes eliminar una entidad al llamar a RemoveFromParent() en la entidad, y puedes eliminar un componente de una entidad si llamas a RemoveFromEntity() en el componente. Las entidades y componentes eliminados pueden volver a añadirse a la escena con AddEntities() y AddComponents(), respectivamente. Ten en cuenta que no puedes cambiar la entidad padre de los componentes eliminados que vuelvas 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 componentes definidos en tu prefabricado son accesibles en Verse a través de las llamadas a GetEntities() y GetComponents() en un prefabricado.
Puedes generar instancias de tus prefabricados instanciando la clase prefabricado y añadiéndolas a una entidad de la escena. En el siguiente ejemplo, el componente de Verse crea una instancia del prefabricado, nombrado loop_disappearing_platform_prefab en el editor, 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
Cuando crees tus propios componentes en Verse, ten en cuenta las siguientes prácticas recomendadas y sugerencias:
Los componentes de Verse que dependen de otros componentes deben estar generalmente en la misma entidad.
Los componentes exponen eventos de tic de prefísica y posfísica, que se producen en cada fotograma. Esto es útil si necesitas realizar cierta lógica antes de que se aplique la física, como modificar la transformación, y después, por ejemplo, para leer las posiciones de los objetos después de la física.
Si no necesitas específicamente los eventos de prefísica o posfísica, debes seguir utilizando las expresiones de simultaneidad de Verse para controlar el flujo temporal en función de cierta lógica. Para obtener más información, consulta Flujo de tiempo y simultaneidad.
Las funciones de duración de los componentes son diferentes de la duración de los dispositivos. La lógica de los componentes funciona tanto en el modo de edición como en el de juego. Si quieres que la lógica de tu componente solo se ejecute cuando se inicie el juego, puedes generar prefabricados en la función
OnBegin()de un dispositivo Verse.