Edit 12.03.2017
On request I have created a simple sample project that reproduces the error. Here it is: [InterfaceTest Project][1]
The Project contains the following contents:
- Interface (C++) named
ListenerInterface
- Two UMG UserWidgets implementing the interface (oververriding the interface event
OnPropertyChanged
)- One Widget implements the interface directly in Blueprint (via the Class Settings property sheet)
- The Other Widget has a C++ base class (
UMyCppUserWidget
) that implements the interface
- An Actor
BP_MyActor
with a componentMyActorComponent
(and owning the two widgets) - The
MyActorComponent
has the functionRegisterListener
where theListenerInterface
can be registered - The member function
UMyActorComponent::ChangePropertyAndNotiyListener
changes the property value and notifies the registered listener by calling the Interface function callbackOnPropertyChanged
, that is implemented/overridden by the both user widgets.
Steps to reproduce:
- Start the editor from visual studio or attach the debugger to the editor.
- Start the game inside the editor
- Enable Mouse cursor by pressing shift+F1
- Click the first button on the left widget
This should trigger the check()
assertion as shown in this picture: Note that the InterfacePointer
is invalid (NULL), while the ObjectPointer
looks good.
When doing the same steps in the right widget, you will get the following (using a manual breakpoint): As you can see the InterfacePointer
is valid here:
(I cannot attach more screenshot, please let me know if you need it, I will then delete the screens from the original message.)
Please let me know if you need any further information.
Original Post below
I’m implementing a listener mechanism for variable replication inside actor components. The listener interface shall be implemented by interested classes or blueprints.
The classes/blueprints that implement the interface must register themselves via function call on the Component.
The Component has a UPROPERTY(ReplicatedUsing)
from where the notifications are sent to the registered listener, if any.
This does not work if a blueprint implements the interface, the picture shows the registration call, where the debugger shows the correct object reference, but InterfacePointer is null..
As the next picture shows, it does work if I rebase the blueprint to a C++ base, the C++ base implements the interface. The regisitration is still called from blueprint.
Here is the definition of the interface:
#pragma once
#include "ComponentReplicationListener.generated.h"
UINTERFACE(BlueprintType)
class UComponentReplicationInterface : public UInterface
{
GENERATED_UINTERFACE_BODY()
};
inline UComponentReplicationInterface::UComponentReplicationInterface(const class FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{}
class IComponentReplicationInterface
{
GENERATED_IINTERFACE_BODY()
public:
UFUNCTION(BlueprintNativeEvent, Category=ComponentReplicationInterface)
void OnComponentReplication(class UEntityComponentBase* replicatedComponent);
};
Here is the blueprint snippet of the registration. The Blueprint is derived from UUserWidget.
This is the c++ base, for which it is working.
#pragma once
#include "Blueprint/UserWidget.h"
#include "events/ComponentReplicationListener.h"
#include "RuneInTreeWidget.generated.h"
/**
*
*/
UCLASS(BlueprintType)
class GAME_API URuneInTreeWidget : public UUserWidget, public IComponentReplicationInterface
{
GENERATED_BODY()
public:
virtual void OnComponentReplication_Implementation(class UEntityComponentBase* replicatedComponent) override;
};