Esta página te guía a través de la creación de un nuevo componente de Scene Graph llamado trigger_component. Este componente activa acciones en entidades, las cuales tienen un componente de Scene Graph que implementa la interfaz que se puede activar. El trigger_component ofrece a los agentes una forma de interactuar con Scene Graph a través de un volume_device. Cuando un agente entra o sale del volume_device, se señala el AgentEnteredEvent y el AgentExitedEvent correspondientes y se llama a las devoluciones de llamada correspondientes para realizar acciones en los componentes y las entidades de Scene Graph.
En la siguiente imagen, el pedestal blanco en el suelo es una entidad de Scene Graph con el trigger_component y un volume_device invisible alrededor del pedestal.
Cuando el jugador se sube al pedestal, el trigger_component activa las dos luces más a la derecha.
Cuando el jugador se baja del pedestal y deja el volume_device, las luces permanecen encendidas.
Para obtener más información sobre las funciones del lenguaje de Verse utilizadas en esta página, consulta lo siguiente:
Define el Trigger Component
Ve al explorador de Verse, haz clic derecho en el nombre del proyecto y elige Añadir nuevo archivo de Verse al proyecto.
Elige la plantilla de componente de Scene Graph y cambia el nombre del componente a trigger_component.
Define la
clasede trigger_component y añade campos que hagan referencia alvolume_deviceasociado, independientemente de si este componente solo activa los elementos derivados o todos los descendientes que se pueden activar, y una matriz que haga referencia a todos los agentes que interactúan con este componente.Versetrigger_component := class<final_super>(component): # volume_device associated with this trigger_component @editable InteractionVolume<private>:volume_device = volume_device{} # whether or not this triggers on components on child entities @editable OnlyTriggerChildren:logic = falseAñade funciones denominadas
OnAgentEntersVolumeyOnAgentExitsVolumeque definan lo que sucede cuando un agente entra y sale delvolume_deviceasociado a este componente. Cuando un agente ingresa al volumen, registra el agente que interactúa y busca las entidades descendientes que tienen un componente que implementa la interfazque se puede activary, luego, activa el componente en esas entidades. Cuando un agente ingresa al volumen, elimina al agente que interactúa de la lista de agentes que interactúan con este volumen.Verse# Event that is triggered when an Agent enters the InteractionVolume OnAgentEntersVolume(Agent:agent):void= for: ChosenEntity : Entity.FindDescendantEntities(entity) ChosenEntityComponent : ChosenEntity.GetComponents() CastToInterface := triggerable[ChosenEntityComponent] do: if (OnlyTriggerChildren?): if (Entity = ChosenEntity.GetParent[]): CastToInterface.Trigger()Conecta las funciones
OnAgentEntersVolumeyOnAgentExitsVolumealvolume_deviceregistrándolas como funciones de devolución de llamada paraAgentEntersEventyAgentExitsEventen la funciónOnSimulatede este componente.Verse# 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() # 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.
Define los componentes que se pueden activar
A continuación, define los componentes que implementan la interfaz que se puede activar creada anteriormente. Estos son componentes que se añaden a entidades de Scene Graph que son descendientes de una entidad con un puzzle_component y son activados por una entidad ancestral con un trigger_component. En este tutorial, se definen tres componentes que se pueden activar diferentes:
triggerable_mesh_component: activa/desactiva la visibilidad delmesh_componentde la entidad.triggerable_light_component: activa/desactiva elsphere_light_componentde la entidad e intercambia elmesh_componentde la entidad por uno con o sin color emisivo, en función de si la luz está encendida o apagada.triggerable_movement_component: activa/desactiva una transformación delmesh_componentde la entidad mediante elkeyframed_movement_component.
Estos tres componentes diferentes comparten una gran cantidad de funcionalidad, y muchas de las funciones se definen de la misma manera. Para empezar, crea un nuevo archivo de Verse vacío llamado TriggerableComponents.verse.
Incluye los siguientes módulos:
/Verse.org/SceneGraph, ya que este archivo usa componentes de Scene Graph y eventos de escena.
/Verse.org/SceneGraph/KeyframedMovement, ya que este archivo utiliza keyframed_movement_delta.
/Verse.org/Simulation, ya que este archivo usa el atributo @editable.
/Verse.org/SpatialMath, ya que este archivo usa transformaciones de Verse.
Verseusing { /Verse.org/SceneGraph } using { /Verse.org/SceneGraph/KeyframedMovement } using { /Verse.org/Simulation } using { /Verse.org/SpatialMath }Define los componentes
triggerable_mesh_component,triggerable_light_componentytriggerable_movement_component. Todos estos componentes heredan de la clase base decomponentee implementan la interfaz que se puede activar.Los tres componentes implementan los mismos tres eventos:
OnReceive: se llama cuando este componente recibe un evento de escena.OnBeginSimulation: se llama cuando el componente debería comenzar a simular.OnSimulate: se llama cuando el componente comienza a simular.
Añade las siguientes implementaciones a los tres componentes.
Verse# Runs when this component receives a scene event OnReceive<override>(SceneEvent:scene_event):logic= if (PuzzleSolvedEvent := puzzle_solved_event[SceneEvent], not PuzzlePiece?): Trigger() true false # Runs when the component should start simulating in a running game. OnBeginSimulation<override>():void = # Run OnBeginSimulation from the parent class beforeLos tres componentes también implementan la anulación
PostTriggerde la interfazque se puede activarde la misma manera mediante el envío de untriggered_eventsi el componenteque se puede activares una pieza de rompecabezas. No puedes lograr esto dentro de la propia interfazque se puede activarporque Verse necesita saber quéentidadse activa, y el campoEntidades parte de la clase decomponentey no está disponible para la interfazque se puede activarsin la dependencia adicional de la clase decomponente.VersePostTrigger<override>():void = if (PuzzlePiece?): Event := triggered_event: Triggered := Triggered TriggeredEntity := option{Entity} Entity.SendUp(Event)
Mesh Component que se puede activar
El triggerable_mesh_component activa/desactiva la visibilidad de un mesh_component en una entidad. Esto requiere ofrecer anulaciones para las siguientes funciones de interfaz que se pueden activar:
SetInitialTriggeredStatePerformActionPerformReverseAction
El estado activado inicial se determina comprobando si la malla comienza o no como visible en el entorno del juego según lo establecido en el panel de detalles del mesh component.
La acción para el
triggerable_mesh_componentes hacer visible la malla delmesh_component. Para hacer esto, recupera elmesh_componentpara la entidad correspondiente, establece la malla en visible y, luego, establece eltriggerable_mesh_componenten el estado activado.Verse# Determine the initial triggered state of this component SetInitialTriggeredState<override>():void= if (MeshComponent := Entity.GetComponent[mesh_component], MeshComponent.Visible?): set Triggered = trueLa acción inversa para el
triggerable_mesh_componentes hacer invisible la malla delmesh_component. Para hacer esto, recupera elmesh_componentpara la entidad correspondiente, establece la malla en no visible y, luego, establece eltriggerable_mesh_componenten el estado no activado.VersePerformReverseAction<override>():void = if (MeshComponent := Entity.GetComponent[mesh_component]): if (MeshComponent.Visible?): set MeshComponent.Visible = false set Triggered = false
Movement Component que se puede activar
El triggerable_movement_component activa una entidad para moverse de una ubicación a una serie de otras ubicaciones en secuencia utilizando el keyframed_movement_component. Esto requiere ofrecer anulaciones para las siguientes funciones de interfaz que se pueden activar:
SetInitialTriggeredStatePerformActionPerformReverseAction
Además, este componente utiliza algunas funciones de ayudante:
GetMovementStates: recupera transformaciones de entidades derivadas que definen la serie de transformaciones para esta entidad.MakeDeltaTransform: crea una transformación delta entre dos transformaciones de entrada.ConstructKeyframeDeltas: crea una matriz de objetoskeyframed_movement_deltapara la entrada delkeyframed_movement_component.SetAndPlayAnimation: asigna los fotogramas clave y reproduce la animación de movimiento.
Añade un float editable a esta clase que determina cuánto dura la animación con fotogramas clave.
Verse@editable Duration:float = 2.0Esta clase implementa la interfaz
que se puede activar, por lo que es necesario brindar anulaciones para las funcionesPerformActionyPerformReverseAction, ya que no tienen implementaciones predeterminadas. Como no hay un estado activado inicial y la acción es un movimiento entre ubicaciones, el estado activado inicial predeterminado es falso. Esto es lo que hace la implementación base en la interfazque se puede activar, por lo que esta función no requiere una anulación en esta clase de componente.La acción para el
triggerable_movement_componentes mover la entidad a lo largo de la serie de transformaciones definidas por las entidades derivadas.VersePerformAction<override>():void = MovementStates := GetMovementStates() AnimationFrames:[]keyframed_movement_delta = ConstructKeyframeDeltas(MovementStates) SetAndPlayAnimation(AnimationFrames)La acción inversa para el
triggerable_movement_componentes mover la entidad a lo largo de la serie de transformaciones definidas por las entidades derivadas en orden inverso. Esta función es similar aPerformActionexcepto que la matriz de transformación está en orden inverso.VersePerformReverseAction<override>():void = MovementStates := GetMovementStates() ReversedMovementStates := for: Index := 0..MovementStates.Length - 1 ReversedElement := MovementStates[MovementStates.Length - 1 - Index] do: ReversedElement AnimationFrames := ConstructKeyframeDeltas(ReversedMovementStates) SetAndPlayAnimation(AnimationFrames)Define las funciones de ayudante que utiliza este componente. Primero, crea una función llamada
GetMovementStatespara recuperar las transformaciones a las que se mueve este movimiento.VerseGetMovementStates():[]transform= for (ChildEntity : Entity.FindDescendantEntities(entity), Entity = ChildEntity.GetParent[]): ChildEntity.GetGlobalTransform()Define una función de ayudante denominada
MakeDeltaTransformque construya una transformación delta entre dos transformaciones. Una transformación delta, D, de la transformación A a la transformación B es la transformación tal que cuando la transformación D se aplica a la transformación A, el resultado es la transformación B.Para ampliar esto, supongamos que tienes una entidad de Scene Graph con la transformación actual A, pero deseas escalar, rotar y trasladar tu entidad para que tenga la transformación B. La transformación delta D es la transformación que necesitas para un
keyframed_movement_deltaa fin de animar el movimiento de tu entidad de la transformación A a la transformación B.VerseMakeDeltaTransform(InTransformOne:transform, InTransformTwo:transform):transform = transform: Translation := InTransformTwo.Translation - InTransformOne.Translation Rotation := MakeComponentWiseDeltaRotation(InTransformOne.Rotation, InTransformTwo.Rotation) Scale := vector3: Forward := InTransformTwo.Scale.Forward / InTransformOne.Scale.Forward Right := InTransformTwo.Scale.Right / InTransformOne.Scale.Right Up := InTransformTwo.Scale.Up / InTransformTwo.Scale.UpDefine un ayudante denominado
ConstructKeyframeDeltaque cree una matriz de objetoskeyframed_movement_deltapara la entrada a la animaciónkeyframed_movement_component.VerseConstructKeyframeDeltas<public>(MovementStates:[]transform):[]keyframed_movement_delta = var LastTransform:transform = Entity.GetGlobalTransform() for (EntityIndex -> CurrentTransform : MovementStates): DeltaTransform := MakeDeltaTransform(LastTransform, CurrentTransform) set LastTransform = CurrentTransform keyframed_movement_delta: Transform := DeltaTransform Duration := Duration Easing := if (MovementStates.Length > 1): if (EntityIndex = 0):Crea una función denominada
SetAndPlayAnimationque asigne la matrizkeyframed_movement_deltaa la animaciónkeyframed_movement_componenty la reproduzca.VerseSetAndPlayAnimation<private>(Frames:[]keyframed_movement_delta):void = if (KeyframedMovementComponent := Entity.GetComponent[keyframed_movement_component]): KeyframedMovementComponent.SetKeyframes(Frames, oneshot_keyframed_movement_playback_mode{}) KeyframedMovementComponent.Play()
Light Component que se puede activar
El triggerable_light_component enciende y apaga una luz. Esto requiere ofrecer anulaciones para las siguientes funciones de interfaz que se pueden activar:
SetInitialTriggeredStatePerformActionPerformReverseAction
El estado activado inicial de la luz depende de si está encendida o no, por lo que
SetInitialTriggeredStatecomprueba si la luz ya está encendida y, si lo está, la establece como activada inicialmente.Verse# Determine the initial triggered state of this light SetInitialTriggeredState<override>():void= for: DescendantEntity : Entity.FindDescendantEntities(entity) Entity = DescendantEntity.GetParent[] MeshComponent := DescendantEntity.GetComponent[mesh_component] LightComponent := DescendantEntity.GetComponent[light_component] MeshComponent.IsEnabled[] LightComponent.IsEnabled[] do:La acción que realiza
triggerable_light_componentes encender la luz y cambiar a una malla que indica que la luz está encendida.VersePerformAction<override>():void= if (not IsLightOn?): for (DescendantEntity:Entity.FindDescendantEntities(entity), Entity = DescendantEntity.GetParent[]): if (MeshComponent := DescendantEntity.GetComponent[mesh_component]): if (LightComponent := DescendantEntity.GetComponent[light_component]): MeshComponent.Enable() LightComponent.Enable() else: MeshComponent.Disable() set IsLightOn = trueLa acción que realiza el
triggerable_light_componentes apagar la luz y hacer visible elmesh_componentno emisivo.VersePerformReverseAction<override>():void= if (IsLightOn?): for (DescendantEntity:Entity.FindDescendantEntities(entity), Entity = DescendantEntity.GetParent[]): if (MeshComponent := DescendantEntity.GetComponent[mesh_component]): if (LightComponent := DescendantEntity.GetComponent[light_component]): MeshComponent.Disable() LightComponent.Disable() else: MeshComponent.Enable() set IsLightOn = false
Próximos pasos
Ahora que se escribió todo el código de Verse, compila tu código de Verse. A continuación, construye prefabricados con entidades y componentes base que puedas reutilizar en UEFN para crear tu propia experiencia de rompecabezas.
Código final
TriggerComponent.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/SceneGraph }
using { Logging }
trigger_component<public> := class<final_super>(component):
@editable
InteractionVolume<private>:volume_device = volume_device{}
TriggerableComponents.verse
using { /Verse.org/SceneGraph }
using { /Verse.org/SceneGraph/KeyframedMovement }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
EnabledToolTip<public><localizes>:message = "Whether or not this component is enabled."
triggerable_mesh_component<public> := class<final_super>(component, triggerable):
<# Triggerable interface #>