OnAction from UiCanvasNotificationBus::Handler isn't called

,

Hello, I’m testing the UI from the Lumberyard but I’m stuck with the actions of the UI.
For now, I’m just trying to use the action of one button in C++ but the method OnAction is never called.

For the test, I’ve created a canvas with one button and set a string on the click action field.
The canvas is linked to the same entity as my handler with the UI Canvas Asset Ref component.

Here is the C++ code.
Can someone help me to understand what I did wrong ? Thanks.

.h

	class UiActionComponent :
public AZ::Component,
public UiCanvasNotificationBus::Handler
{
public:
AZ_COMPONENT(UiActionComponent, "{6AC2B681-E90E-4B2E-A407-12EBE39939BB}");
static void Reflect(AZ::ReflectContext* context);
void Init() override {}
void Activate() override;
void Deactivate() override;
void OnAction(AZ::EntityId entityId, const LyShine::ActionName& actionName) override;
};

.cpp

	void UiActionComponent::Activate() {
UiCanvasNotificationBus::Handler::BusConnect(m_entity->GetId());
}
void UiActionComponent::Deactivate() {
UiCanvasNotificationBus::Handler::BusDisconnect();
}
void UiActionComponent::OnAction(AZ::EntityId entityId, const LyShine::ActionName& actionName)
{
OutputDebugString(actionName.c_str());
}

Hi @2Eviers,

Thanks for the question.

There are two different entities involved here. There is the in-world entity that the the UiCanvasAssetRefComponent is on and there is a separate canvas entity that is loaded as part of the canvas. You are connecting to the bus with the entityId of the former but it needs to be the latter.

There is a bus that allows you to get the canvas entity from the UiCanvasAssetRefComponent. You can add a method like this to your component (like the UiCanvasOnMeshComponent does) to get it for you:

    AZ::EntityId UiCanvasOnMeshComponent::GetCanvas()
{
AZ::EntityId result;
EBUS_EVENT_ID_RESULT(result, GetEntityId(), UiCanvasRefBus, GetCanvas);
return result;
}

However, there is a potential “order of activation issue” here. If you send this bus message in the activate for your component, this depends on the UiCanvasAssetRefComponent being activated before your component. This should be true so long as the GetRequiredServices method on your component lists the UiCanvasRefService like this:

    static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC("UiCanvasRefService", 0xb4cb5ef4));
}

However, the UiCanvasAssetRefComponent does not always load the canvas in its activate. So a better solution is to connect to the UiCanvasNotificationBus in the OnCanvasLoadedIntoEntity notification method. That method actually passes in the entityId that you need to connect to.

To do this would would connect to the UiCanvasAssetRefNotificationBus in your activate. See the UiCanvasOnMeshComponent for an example.

So your Activate would look like this:

    void UiActionComponent::Activate()
{
UiCanvasAssetRefNotificationBus::Handler::BusConnect(GetEntityId());
}

and you would implement this method:

    void UiActionComponent::OnCanvasLoadedIntoEntity(AZ::EntityId uiCanvasEntity)
{
UiCanvasNotificationBus::Handler::BusConnect(uiCanvasEntity);
}

Let me know if that works for you

Hey @2Eviers — I’ve sent a note about this to our team; will update you as soon as I can :slight_smile:

Yes it works, Thank you. For my case the canvas is loaded automaically so I use the first solution with the required service. I tried the OnCanvasLodedIntoEntity but for me the method was not called. It was called only if I load the canvas later.