I am trying to implement a context action object listener, i.e, an object that performs an action when the player is within its reach and presses an action button. (door switch for instance)
I managed to do it with blueprints using OnBeginOverlap/ Input Action and a Gate, but Iād like to learn how to do it in c++. Everything is ok but the input listening piece in the Actor. Iām enabling it using:
AutoReceiveInput = EAutoReceiveInput::Player0;
I followed the docs (Input Action And Axis Mappings In UE4 - Unreal Engine) and it says I could bind anywhere I have access to an UInputComponent, but as off now I only know how get an reference to it via SetupPlayerInputComponent() which is only defined in Character.
I use this for my interaction with object, so upon Overlap i will bind my delegate to function of that object, so when i press e, it will execute that function to do what you want with object. Btw you can unbind when you end overlap
I was looking for a way to bind an input to an actor, but you actually gave me a much better way of doing it.
The way I did was to bind a delegate function to OnBegin/OnEnd Overlap that registers/unregisters an object as a input listener. When the action event is trigger is passes the message to the listener allowing it to perform its action.
The code follows in case this helps someone else:
// InteractiveActor.h
UCLASS()
class VIRTUALTRAINING_API AInteractiveActor : public AActor
{
GENERATED_UCLASS_BODY()
/** Defines a Context Area. All input outside its reach is ignored */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Trigger")
TSubobjectPtr<USphereComponent> Trigger;
/** Called when an Action Input happens within the Context Area of this Actor */
UFUNCTION(BlueprintImplementableEvent, meta=(FriendlyName = "OnAction"))
virtual void OnContextAction();
};
The OnContextAction can be implemented by InteractiveActor subclasses and/or via blueprints.
// Character.h
UCLASS()
class FOO_API AVTCharacter : public ACharacter
{
GENERATED_UCLASS_BODY()
...
/* Listerner to Action Events */
UPROPERTY()
class AInteractiveActor* ActionListener;
UFUNCTION(BlueprintCallable, Category = "Action")
void OnContextAction();
...
}
// Character.cpp
AVTCharacter::AVTCharacter(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
// Delegate Binding
OnActorBeginOverlap.AddDynamic(this, &AVTCharacter::OnRegisterActorAsListener);
OnActorEndOverlap.AddDynamic(this, &AVTCharacter::OnUnregisterActorAsListener);
ActionListener = nullptr;
}
void AVTCharacter::OnContextAction()
{
if (ActionListener)
{
ActionListener->OnContextAction();
}
}
I have a switch class which inherits from InteractiveActor and implements OnContextAction calling the base method (Super::OnContextAction). The base method is implemented in blueprints.
This way I can implement simple things like setting shader parameter in code and other internal states, and still implement more complicated/event driver gameplay in the blueprint (like opening a door);