Version:

第27章 ScriptCanvas

第27章 ScriptCanvas

介绍

注意:
本章的资源可以在 GitHub 上找到,网址为: https://github.com/AMZN-Olex/O3DEBookCode2111/tree/ch27_scriptcanvas

我们本章的目标是让鸡用拍打的动作来庆祝每个进球。我们创建了动画图来支持该动画。每当进球时,我们需要将 ‘Celebrating’ animation 参数设置为 true。我们可以使用 C++ 来做到这一点,但这是一个很好的机会,可以向您展示如何使用可视化脚本执行相同的工作。

Script Canvas 是 O3DE 中的一个可视化脚本工具。例如,这是一个可视化节点,它等效于 SetNamedParameterBool 的 C++ 方法,该方法类似于我们在前面章节中使用的方法。

例 27.1.Set Named Parameter Bool

提醒一下,GoalDetectorComponent 会在进球得分时发出通知。

void GoalDetectorComponent::UpdateUi()
{
  UiScoreNotificationBus::Broadcast(
  &UiScoreNotificationBus::Events::OnTeamScored, m_team);
}

我们需要注册才能接收此事件,并将 Anim Graph 组件上的 Celebration 参数设置为 true。

Behavior Context

为了让 Script Canvas 为您提供新的自定义通知事件总线的节点,我们必须将该事件总线反映到 Behavior Context。以下是反映通知总线的步骤。

  1. 这是我们反映的公交车。
class UiScoreNotifications
: 
public AZ::ComponentBus
{
public:
virtual void OnTeamScored(int team) = 0;
};
using UiScoreNotificationBus = AZ::EBus<UiScoreNotifications>;
  1. 为其创建行为处理程序。
class ScoreNotificationHandler
  1. 从您希望反射到脚本的事件总线和 AZ::BehaviorEBusHandler 继承。
class ScoreNotificationHandler
: public UiScoreNotificationBus::Handler
, public AZ::BehaviorEBusHandler
  1. 列出您希望通过宏反射AZ_EBUS_BEHAVIOR_BINDER所有方法。在本例中,只有 OnTeamScored。
AZ_EBUS_BEHAVIOR_BINDER(ScoreNotificationHandler,
"{33B5BC25-622B-4DF0-92CF-987CC6108C31}",
AZ::SystemAllocator,
OnTeamScored);
提示:

如果有更多方法要反映,则可以在宏末尾一次列出一个方法。

AZ_EBUS_BEHAVIOR_BINDER(ScoreNotificationHandler,
  "{33B5BC25-622B-4DF0-92CF-987CC6108C31}",
  AZ::SystemAllocator,
  Method1,
  Method2,
  Method3);
  1. 覆盖每个方法以调用由 AZ_EBUS_BEHAVIOR_BINDER 生成的 FN_ 方法。例如,OnTeamScored 有 FN_OnTeamScored 。
void OnTeamScored(int team) override
{
  Call(FN_OnTeamScored, team);
}
  1. 向 BehaviorContext 注册此处理程序。它可以在任何 Reflect 方法中完成。例如,在 GoalDetectorComponent 中。这是一个好位置,因为它会在其上调用事件。另一个不错的选择是将其放在 Gem 或项目的 system 组件中。
void GoalDetectorComponent::Reflect(AZ::ReflectContext* rc)
{
 //...
 if (auto bc = azrtti_cast<AZ::BehaviorContext*>(rc))
    {
        bc->EBus<UiScoreNotificationBus>("ScoreNotificationBus")
            ->Handler<ScoreNotificationHandler>();
    }
 }
提示:

如果要将要从 Script Canvas 调用的方法反映到 C++ 中,则只需几行 C++ 代码。例如,下面是我们在本章开头看到的 SetNamedParameterBool 的反射。

behaviorContext->EBus<AnimGraphComponentRequestBus>(
"AnimGraphComponentRequestBus")
> Event("SetNamedParameterBool",
> &AnimGraphComponentRequestBus::Events::SetNamedParameterBool)

你可以在这里看到这个定义:C:\git\o3de\Gems\EMotionFX\Code\Source\Integration\Components\AnimGraphComponent.cpp。

构建 Canvas

编译项目后,您可以重新打开 Editor 并创建新的脚本画布。以下是从 Script Canvas 设置 Celebration 参数的步骤。

  1. 转到 Chicken_Actor 实体。(它有 Anim Graph (动画图形) 组件。
  2. 将 Script Canvas 组件添加到实体。
  3. 使用 Script Canvas 中的工具或从 Script Canvas 组件上的图标→打开 Script Canvas 编辑器。
  4. 进入 Script Canvas 编辑器后,使用 File → New Script 启动新脚本。
  5. 在 Node Pallete 中,搜索“Score Notification Bus”。

  1. 将 OnTeamScored 拖放到空白的画布空间中。
  2. 在 Node Palette 中搜索 “Set named parameter bool”。也可以将其拖放到画布中。

  1. 将 OnTeamScored 的执行行连接到“Set Named Parameter Bool”节点上的 In execution 连接器。通知节点将在调用事件时开始执行脚本。执行将传递到 “Set Named Parameter Bool” 节点。之后,Out 连接器会将执行传递给下一个节点(如果已连接)。

图 27.1.两个 Script Canvas 节点

  1. 在“Set Named Parameter Bool”节点上,将 Value 设置为 Celebrating。
  2. 将布尔值设置为选中。
  3. 将画布保存在项目或其中一个 Gem 下,例如在 C:\git\book\MyProject\scriptcanvas\celebrate.scriptcanvas 中。
  4. 返回到Chicken_Actor实体。
  5. 在 Script Canvas 组件上,将新画布分配给 Script Canvas Source File(Script Canvas 源文件)属性。

例 27.2.Chicken_Actor 具有 Script Canvas 组件的实体

使用此组件,每当进球时,鸡都会播放庆祝拍打动作两秒钟。

小结

注意:
本章的源代码和资源可以在 GitHub 上找到,网址为: https://github.com/AMZN-Olex/O3DEBookCode2111/tree/ch27_scriptcanvas

以下是本章中的 C++ 代码更改。

例 27.3.GoalDetectorComponent.cpp 中的新代码

 void GoalDetectorComponent::Reflect(AZ::ReflectContext* rc)
    {
 //...
 if (auto bc = azrtti_cast<AZ::BehaviorContext*>(rc))
        {
            bc->EBus<UiScoreNotificationBus>("ScoreNotificationBus")
                ->Handler<ScoreNotificationHandler>();
        }
    }

例 27.4. UiScoreBus.h

 #pragma once
 #include <AzCore/Component/ComponentBus.h>
 #include <AzCore/RTTI/BehaviorContext.h>
 namespace MyGem
 {
 class UiScoreNotifications
        : 
public AZ::ComponentBus
    {
 public:
 virtual void OnTeamScored(int team) = 0;
    };
 using UiScoreNotificationBus = AZ::EBus<UiScoreNotifications>;
 /// NEW
 class ScoreNotificationHandler
        : 
        , 
public UiScoreNotificationBus::Handler
 public AZ::BehaviorEBusHandler
    {
 public:
        AZ_EBUS_BEHAVIOR_BINDER(ScoreNotificationHandler,
 "{33B5BC25-622B-4DF0-92CF-987CC6108C31}",
            AZ::SystemAllocator, OnTeamScored);
 void OnTeamScored(int team) override
        {
            Call(FN_OnTeamScored, team);
        }
    };
 }
注意:
您可以在以下位置找到有关如何将各种类、结构和接口反射到 Behavior Context 的文档: https://docs.o3de.org/docs/user-guide/programming/components/reflection/behavior-context/