Skip to content

Interactable Interface Pattern

Andromeda uses an Unreal interface so different object types can respond to the same player input.

The current interaction contract is:

CanInteract(APawn* InteractingPawn) -> bool
GetInteractPrompt() -> FText
Interact(APawn* InteractingPawn) -> void

This lets the character avoid knowing whether the focused target is a salvage item, scanner, tagging bench, warehouse zone, or reusable interactable component.

Two Interface Types

Unreal interfaces have two generated-facing types:

UAndromedaInteractableInterface
IAndromedaInteractableInterface

The U... type is the reflected Unreal type. It lets the engine, editor, and Blueprint system know the interface exists.

The I... type is the C++ interface body. That is where the callable functions live from the C++ perspective.

This looks strange compared with Java or Go, where an interface is usually one thing. In Unreal, the split exists because reflection and native C++ both need representation.

BlueprintNativeEvent And _Implementation

The interface functions are BlueprintNativeEvent. That means:

C++ can provide a default implementation.
Blueprint can override the behavior later.

For a BlueprintNativeEvent function named Interact, the C++ implementation is written as:

void SomeClass::Interact_Implementation(APawn* InteractingPawn)

The underscore naming is an Unreal-generated convention. It is an exception to the usual project naming preference because Unreal expects this suffix for native event implementation.

Do not call _Implementation directly from gameplay code. Use Unreal's generated dispatch function:

IAndromedaInteractableInterface::Execute_Interact(Target, Pawn);

That call correctly handles either C++ implementation or Blueprint override.

Actor vs Component Implementation

There are two patterns in the project:

AAndromedaSalvageItem       implements the interface directly.
AAndromedaItemStation       implements the interface directly.
UAndromedaInteractableComponent provides reusable component behavior.

The component exists because some future objects may only need simple prompt-plus-event behavior without a custom actor class. The current major gameplay actors implement the interface directly because their interaction behavior is specific.

Same Input, Different Behavior

Pressing E does not mean "scan" or "sell." It means "interact with the focused thing."

Examples:

Focused salvage item:
    Interact -> pick up item through carry component

Focused scanner while carrying item:
    Interact -> place item on scanner

Focused scanner with placed item:
    Interact -> open scan result UI

Focused tagging bench with scanned item:
    Interact -> assign package

Focused warehouse zone while carrying packaged item:
    Interact -> place item and process Sell/Quarantine

This is the main reason the interface matters. The character owns input and focus. The target owns meaning.