Modular interact system

I’m trying to make a modular interact system that works like that:
1- All interactable Actors (like a door, a light switch, a shelf…) have a class component called InteractableActor;
2- When the player looks for the interactable actor and press “F” key, the InteractableActor class attached to the interacted actor will call a function that I have previously defined at the details panel.

Example: the player looks at the door and press “F” key, so the door oppens. Then he looks at the light switch and press “F” key, so the light switch turns on.

CONCLUSIOIN: I need to have a field in the details panel that allows me to select a function of interaction for each type of interactable object.

I’m migrating from Unity Engine, and there I used a code like this:



using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class InteractableObject : MonoBehaviour
{
    public UnityEvent onInteract; //The Inspector panel in Unity shows a field to attach a function.

    public void Interact() //When player press "F" key, this function is called.
    {
        onInteract.Invoke();
    }
}


@GustavoDBP what I’d do:

- All interactable Actors (like a door, a light switch, a shelf…) have a class component called InteractableActor;
Create an Interface InteractableActor with Interact() function and implement it in your Actors

- When the player looks for the interactable actor and press “F” key, the InteractableActor class attached to the interacted actor will call a function that I have previously defined at the details panel.
When you “collide” with your Actors check if they implement your InteractableActor. Then call Interact().

- I need to have a field in the details panel that allows me to select a function of interaction for each type of interactable object.
In your Door Actor just implement open/close inside Interact() function, same for your Light switch.

3 Likes

Would recommend an interface:



// Copyright bla

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "MYUseInterface.generated.h"

UINTERFACE(MinimalAPI)
class UMyUseInterface : public UInterface
{
   GENERATED_BODY()

   UMyUseInterface(FObjectInitializer const& ObjectInitializer)
   {}
};

class MYGAME_API IMyUseInterface
{
   GENERATED_IINTERFACE_BODY()

public:
   UFUNCTION(Category = "Use", BlueprintNativeEvent, BlueprintCallable)
   void Use(class AController* Controller, FName UseType);

   UFUNCTION(Category = "Use", BlueprintNativeEvent, BlueprintCallable)
   void ServerUse(class AController* Controller, FName UseType);
};


The pipe that through your player controller:



void AMyPlayerController::UseActor(class AActor* UseTarget, FName UseType)
{
   if (IsValid(UseTarget))
   {
      if (UseTarget->GetClass()->ImplementsInterface(UMyUseInterface::StaticClass()))
      {
         if (GetLocalRole() < ROLE_Authority)
         {
            IMyUseInterface::Execute_ClientUse(UseTarget, this, UseType);
            ServerUseActor(UseTarget, UseType);
         }
         else
         {
            IMyUseInterface::Execute_ServerUse(UseTarget, this, UseType);
         }
      }
   }
}

bool AMyPlayerController::ServerUseActor_Validate(class AActor* UseTarget, const FName& UseType)
{
   return true;
}

void AMyPlayerController::ServerUseActor_Implementation(class AActor* UseTarget, const FName& UseType)
{
   UseActor(UseTarget, UseType);
}


You can always expand it as required, such as adding a special “AIUse” if they need to do something different.

How to decide what to interact with - your call.
e.g. Trace line from center of the screen, be inside a trigger volume.

After that, GetPlayerController()->UseActor(SomeActor) or Blueprint equivalent.

2 Likes

Why do you need to pass player controller to the Use futncion? How do you implement this interface in the actor?

You should pass the controller - AI or player - to make it easy for the usable actor to react who it is being used by.

e.g. A team specific door.

As for how to implement interfaces, either check the link above for UE4 or see Implementing Your Interface in C++ for UE5.