El lienzo de script y el contexto de comportamiento - Guía del usuario de Lumberyard

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

El lienzo de script y el contexto de comportamiento

Puede utilizar Script Canvas de para exponer código de tiempo de ejecución en un entorno de desarrollo visual mediante el contexto de comportamiento. Además de este tema, se recomienda que también lea Guía del programador para entidades y componentes y Contexto de comportamiento.

En el siguiente diagrama de la arquitectura del código se muestra la relación entre Script Canvas y el contexto de comportamiento en Amazon Lumberyard.


            Arquitectura de Script Canvas

El código básico de Script Canvas se ha creado como una biblioteca estática vinculada a la gema dependiente y a la gema Editor. Esto permite que el espacio que ocupa el código en el tiempo de ejecución sea tan pequeño como el mínimo necesario para ejecutar un gráfico de Script Canvas. También permite que la gema Editor de lienzo de scripts contenga todo el código necesario para diseñar y desarrollar gráficos de Script Canvas.

Script Canvas está diseñado para usar el reflejo de contexto de comportamiento y proporcionar acceso a los mismos objetos yEBusEn Lua. Cuando utiliza el contexto de comportamiento, no tendrá que escribir ningún código específico a Script Canvas. Sin embargo, es importante que la forma en la que el código se refleja en el contexto de comportamiento siga siendo intuitiva en un entorno de desarrollo de scripts visuales.

El contexto de comportamiento para Script Canvas incluye los siguientes beneficios:

  • La funcionalidad expuesta mediante el contexto de comportamiento también está disponible en Lua (y cualquier otra solución vinculada al contexto de comportamiento).

  • El sistema EBus facilita el uso de paradigmas de programación desacoplados y basados en eventos.

  • Script Canvas puede utilizar cualquier funcionalidad expuesta en el contexto de comportamiento, incluso aunque provenga de otras gemas. Por lo tanto, cuando se refleja el código en el contexto de comportamiento, las gemas pueden mejorar Script Canvas.

  • La reflexión de gemas en el contexto de comportamiento elimina la necesidad de agregar dependencias de las gemas a Script Canvas.

El componente de la luz y el script Canvas

Para que pueda comprender mejor la relación entre el contexto de comportamiento y Script Canvas, esta sección aborda el componente de la luz, que es bastante sencillo. En el ejemplo se muestra cómo su reflexión del contexto de comportamiento se traduce en nodos de Script Canvas.

Puede utilizar el componente de la luz para aportar una luz a una entidad. Puede configurar la luz mediante la configuración de parámetros como, por ejemplo, color, intensidad y radio. El componente de la luz también se puede activar o desactivar y puede responder a estos eventos cuando ocurran.

La comunicación con un componente de luz de una entidad se realiza mediante dos EBuses: LightComponentRequestBus y LightComponentNotificationBus.

Un bus de solicitud facilita métodos a los que se puede llamar en una entidad. Si una entidad tiene un componente de luz, el componente de luz implementa el comportamiento de las solicitudes que se realizan al mismo.

Algunas de las solicitudes que puede realizar a un componente de luz son las siguientes. Para el código fuente, consulte el archivo dev\Gems\LmbrCentral\Code\include\LmbrCentral\Rendering\LightComponentBus.h.

//! Turns light on. Returns true if the light was successfully turned on virtual bool TurnOnLight() { return false; } //! Turns light off. Returns true if the light was successfully turned off virtual bool TurnOffLight() { return false; } //! Toggles light state. virtual void ToggleLight() {}

Estas solicitudes forman parte del LightComponentRequestBus. Su comportamiento se implementa desde LightComponent.

Para que estas solicitudes sean accesibles para el desarrollo de scripts, deben reflejarse en el contexto de comportamiento. Esto se realiza en LightComponent::Reflect. El código fuente está en el archivo dev\Gems\LmbrCentral\Code\Source\Rendering\LightComponent.cpp.

behaviorContext->EBus<LightComponentRequestBus>("Light", "LightComponentRequestBus") ->Attribute(AZ::Script::Attributes::Category, "Rendering") ->Event("TurnOn", &LightComponentRequestBus::Events::TurnOnLight, "TurnOnLight") ->Event("TurnOff", &LightComponentRequestBus::Events::TurnOffLight, "TurnOffLight") ->Event("Toggle", &LightComponentRequestBus::Events::ToggleLight, "ToggleLight")

Cuando el Canvas de scripts examina el contexto de comportamiento, encuentra estas conexiones y genera automáticamente los nodos correspondientes.


                Nodos del componente Light en Script Canvas

Los EBuses se utilizan para comunicarse con los componentes de la entidad. Para hacerlo, necesita una dirección. Todos EBuses de un componente se derivan de AZ::ComponentBus, al que se pueden dirigir solicitudes con un ID del tipo AZ::EntityId. Por este motivo, todos los nodos de un EBus de un componente tienen una ranura de entrada para un EntityID. La presencia deSelfen laEntityIDhace referencia al campoEntityIDDe la entidad que posee el gráfico de Script Canvas. Sin embargo, este ID puede asignarse a otra entidad o incluso cambiarse a un ID de entidad no válido.


                Self EntityID

El otro bus que refleja el componente de luz en el contexto de comportamiento es LightComponentNotificationBus. El siguiente código fuente también está en el archivo dev\Gems\LmbrCentral\Code\Source\Rendering\LightComponent.cpp.

behaviorContext->EBus<LightComponentNotificationBus>("LightNotification", "LightComponentNotificationBus", "Notifications for the Light Components") ->Attribute(AZ::Script::Attributes::Category, "Rendering") ->Handler<BehaviorLightComponentNotificationBusHandler>();

Los buses de notificación también se denominan controladores de eventos. Puede utilizar estos controladores de eventos en un componente para responder a los eventos que ocurren en el componente. Como parte de la reflexión al contexto de comportamiento, el código anterior especifica que BehaviorLightComponentNotificationBusHandler controla los eventos para el componente de luz.

El código siguiente muestra el enlace para el BehaviorLightComponentNotificationBusHandler y define dos eventos: LightTurnedOn y LightTurnedOff.

class BehaviorLightComponentNotificationBusHandler : public LightComponentNotificationBus::Handler, public AZ::BehaviorEBusHandler { public: AZ_EBUS_BEHAVIOR_BINDER(BehaviorLightComponentNotificationBusHandler, "{969C5B17-10D1-41DB-8123-6664FA64B4E9}", AZ::SystemAllocator, LightTurnedOn, LightTurnedOff); // Sent when the light is turned on. void LightTurnedOn() override { Call(FN_LightTurnedOn); } // Sent when the light is turned off. void LightTurnedOff() override { Call(FN_LightTurnedOff); } };

Script Canvas tiene un nodo que le permite obtener acceso a todos los eventos de EBus. Puede controlar los eventos que le interesen.


                Bus de notificación de luz

Objetos: Ejemplo de PhysicsComponent Ejemplo

Los objetos que se reflejan en el contexto de comportamiento también están disponibles en Script Canvas. Los objetos estén disponibles en forma de variables.

El componente de luz no proporciona objetos, pero el PhysicsComponent proporciona un ejemplo de un objeto reflejado en el contexto de comportamiento. LaCollisionLa clase se refleja como un objeto del contexto de comportamiento al que se puede obtener acceso mediante el uso de variables en Script Canvas. Puede encontrar el siguiente código fuente en el archivo dev\Gems\LmbrCentral\Code\Source\Physics\PhysicsComponent.cpp.

using Collision = PhysicsComponentNotifications::Collision; // Information about a collision event behaviorContext->Class<Collision>() ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value) ->Property("entity", BehaviorValueProperty(&Collision::m_entity)) ->Property("position", BehaviorValueProperty(&Collision::m_position)) ->Property("normal", BehaviorValueProperty(&Collision::m_normal)) ->Property("impulse", BehaviorValueProperty(&Collision::m_impulse)) ->Property("velocities", BehaviorValueGetter(&Collision::m_velocities), nullptr) ->Property("masses", BehaviorValueGetter(&Collision::m_masses), nullptr) ->Property("surfaces", BehaviorValueGetter(&Collision::m_surfaces), nullptr) ;
nota

Durante la versión de vista previa de Script Canvas, las propiedades deben permitir que tanto los getters como los setters sean accesibles en un nodo Script Canvas. Los contenedores, como vectores, no son compatibles en la actualidad. Por este motivo, las velocidades, masas y superficies no proporcionan un setter.

La mayoría de las variables de objetos se establecen como resultado de un evento. En el caso del ejemplo de Collision anterior, la variable Collision se devuelve desde el evento OnCollision.


                Variable Collision

Puede utilizar el siguiente gráfico para definir la variable de colisión:


                Configuración de la variable Collision

Visualización de nombres de parámetros de eventos EBus en nodos Script Canvas

Para mostrar correctamente los nombres de los parámetros de los eventos EBus, asegúrese de especificar nombres personalizados a la hora de adaptar sus eventos al contexto de comportamiento.

Si no especifica los nombres de los parámetros, estos reciben nombres para mostrar predeterminados como "1", "2" o "3", tal y como se muestra en la siguiente imagen:


            Nombres para mostrar de parámetros predeterminados

El siguiente código produjo el nodo de eventos en la imagen:

if (auto behaviorContext = azrtti_cast < AZ::BehaviorContext * >(reflectContext)) { behaviorContext->EBus < MyBus > ("MyBus") // This is the category that appears in the Node Palette window ->Attribute (AZ::Script::Attributes::Category, "Rendering")->Event ("SomeEvent", &MyBus::Events::SomeEvent); }

La siguiente versión del mismo código añade los nombres de parámetros FirstParam y SecondParam y el texto contextual correspondiente a la función Event:

if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext)) { behaviorContext->EBus<MyBus>("MyBus") // This is the category that appears in the Node Palette window ->Attribute(AZ::Script::Attributes::Category, "Rendering") ->Event("SomeEvent", &MyBus::Events::SomeEvent, { { { "FirstParam" , "First Param Tooltip" }, { "SecondParam", "Second Param Tooltip" } } }); }

En la ventana de paletas de nodos, aparecen los nombres de los parámetros tal y como se especifican:


            Nombres para mostrar de parámetros especificados

Sintaxis alternativa

También puede utilizar la siguiente sintaxis alternativa para crear instancias de sustitución de parámetros antes de transmitirlos a la función Event:

if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext)) { AZ::BehaviorParameterOverrides someEventParam1 = { "FirstParam", "First Param Tooltip" }; AZ::BehaviorParameterOverrides someEventParam2 = { "SecondParam", "Second Param Tooltip" }; behaviorContext->EBus<MyBus>("MyBus") // This is the category that appears in the Node Palette window ->Attribute(AZ::Script::Attributes::Category, "Rendering") ->Event("SomeEvent", &MyBus::Events::SomeEvent, { {someEventParam1, someEventParam2} }); }

Problemas comunes de programación

A continuación, se indican algunos problemas comunes que se producen al programar con Script Canvas y el contexto de comportamiento.

Reflejé mi clase en el contexto de comportamiento, pero no aparece en Script Canvas.

Tanto el contexto de serialización como el contexto de comportamiento usan la misma función Reflect:

Reflect(AZ::ReflectContext*)

Un error común es no mantener separados los ámbitos de reflexión. Por ejemplo, es posible que haya colocado por error la reflexión BehaviorContext dentro del ámbito SerializeContext. Los siguientes ejemplos de código muestran el problema y la solución.

Problema

void Example::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) { serializeContext->Class<Example>() ->Version(1) ; // Problem! BehaviorContext is inside the SerializeContext scope and will not get reflected. if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) { behaviorContext->Class<Example>() ->Method("IsValid", &Example::IsValid) ; } } }

Solución

void Example::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) { serializeContext->Class<Example>() ->Version(1) ; } // Correct! Each context requires its own scope as this function is called multiple times (once per context) if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) { behaviorContext->Class<Example>() ->Method("IsValid", &Example::IsValid) ; } }

Expuse un nuevo EBus en el contexto de comportamiento, pero mi controlador no recibe ninguna llamada.

Por ejemplo, ha creado un controlador de EBus y lo ha expuesto correctamente. Sin embargo, cuando intenta recibir el evento en Script Canvas, no se activa.

Esto se debe a un descuido que es fácil de cometer: los controladores de EBus recién implementados deben estar conectados para que puedan recibir eventos. La solución es asegurarse de que su componente se conecte al bus, como en el siguiente ejemplo:

MyBus::BusConnect()

En función del tipo de bus, es posible que tenga que especificar un ID al que conectarse. Para obtener más información, consulte Trabajo con el sistema de bus de eventos (EBus).