Skip to content

Quick Start


How the system works

Three pieces talk to each other every time the player interacts with something:

PieceLives onDoes
RaycastInteractorPlayer GameObjectCasts a ray every frame. Detects interactable objects in front of the camera.
InteractableTargetAny interactable objectCollects all the actions attached to the object and reports them to the interactor.
Action (component, SO, or wrapper)Same object as the targetDefines what happens — open a door, pick up an item, display text.

The player never calls your game logic directly. RaycastInteractor detects a target → the target returns its actions → your input code calls HandleInteraction() → the system executes the selected action → your method runs.


Installation

  1. Open Window › Package Manager.
  2. Click +Add package from disk…
  3. Navigate to the individual.alejandro-de-la-plata-ramos.interaction-system folder and select package.json.

Running the Demo scene

The package includes a Demo sample with a complete working scene. It is plug & play — import it, open the scene, and press Play.

  1. Import the sample

    In Unity, open Window › Package Manager, locate the Interaction System package, expand the Samples section, and click Import next to Demo Scene.

    Then open the imported scene:
    Assets/Samples/Interaction System/1.0.0/Demo Scene/Scenes/SampleScene

  2. Press Play

    The demo is fully self-contained. Input Actions are pre-configured and included with the package. The RaycastInteractor uses the Default layer mask, which is the layer all demo interactables are already on.

    No extra setup is needed — the scene works immediately out of the box.


Up and running in 5 minutes

You do not need to write any scripts for basic interactions. The base InteractableAction component works out of the box — fill in the fields in the Inspector and wire the OnExecuted event directly to any method on your existing scripts.

  1. Add RaycastInteractor to the Player

    Select your player GameObject and add the component:
    Component › FireSoftworks › Interaction › Raycast Interactor

    In the Inspector, assign Player Camera to your scene camera. That is the only required field — the rest have sensible defaults.

  2. Add InteractableAction to the interactable object

    Select the object and add:
    Component › FireSoftworks › Interaction › Interactable Action

    InteractableTarget is added automatically — you don’t need to add it separately. InteractableAction is marked [RequireComponent(typeof(InteractableTarget))], so Unity adds the target for you the moment you add any action component.

    Fill in the Inspector fields:

    FieldExample valueWhat it does
    IdopenInternal key used to sort actions alphabetically.
    Display NameOpenThe label shown in the HUD.
    Icon(optional Sprite)Icon displayed next to the label.
    On ExecutedDoorController.Open()This is the key field. Wire it to any method on any script in the scene.

    The On Executed event fires every time the player executes this action. The target method can have no parameters (Unity calls it as a static binding) or accept an InteractionContext parameter (Unity passes the live context).

    Example wiring in Inspector:
    ┌─ On Executed (InteractionContext) ──────────────────┐
    │ Runtime DoorController (on this GameObject) │
    │ ▼ Open () │
    └─────────────────────────────────────────────────────┘
  3. Control availability by enabling / disabling

    Add two InteractableAction components to the same object — one labelled Open, one labelled Close — and enable only the one that makes sense at any given moment:

    // Enable/disable from any script that knows the current state.
    openAction.enabled = !isOpen;
    closeAction.enabled = isOpen;

    Wire each action’s OnExecuted in the Inspector to the corresponding method on your controller. No IsAvailable() override, no Execute() override, no extra scripts.

  4. Wire the interact input

    Create a script (or add to an existing one) that calls HandleInteraction() when the player presses the interact button.

    // When the interact button is pressed:
    if (interactor.isInteractionAvailable)
    interactor.HandleInteraction();
  5. Press Play

    Point the camera at the object. The interaction prompt appears. Press your interact key. OnExecuted fires — your method runs.


Going deeper

All Inspector fields

RaycastInteractor

FieldDefaultDescription
Player Camera(none — required)The camera from which the detection ray is cast.
Interaction Range6Maximum distance in Unity units at which objects can be detected.
Interactable MaskDefaultLayer mask for the raycast. The demo uses the Default layer. For production, restrict this to a dedicated Interactable layer for better performance.
Show Unavailable ActionstrueWhen enabled, actions whose IsAvailable() returns false are still listed in the HUD (grayed out). Disable to hide them entirely.
Interact To Show ActionsfalseEnables two-step interaction mode — see below.

InteractableTarget

FieldDescription
SO ActionsInteractableActionSO assets to include. Component-based InteractableAction components are discovered automatically — no list needed for those.
Focused MaterialOptional material applied on top of the object’s renderer when the player aims at it. Useful for an outline/highlight. Leave empty if you handle highlighting yourself.

InteractableAction (and all subclasses)

FieldDescription
IdInternal sort key. Actions are displayed in ascending alphabetical order by Id.
Display NameLabel shown in the HUD.
IconOptional sprite displayed next to the label.
On ExecutedUnityEvent fired after Execute() runs. Wire audio, animators, particle systems — anything with a public method — here without code.

Inspector events on RaycastInteractor

Every C# event on the interactor has a matching UnityEvent you can wire in the Inspector — no subscription code needed for basic setups.

UnityEventPayload typeWhen it fires
On Show Actions DiscoveredActionsDiscoveredEventArgsPlayer aims at an interactable. Use this to show the HUD prompt.
On Action Selection ChangedActionSelectionChangedEventArgsPlayer cycles between actions (e.g. scroll wheel). Use this to highlight the current action.
On Action ExecutedActionExecutedEventArgsAn action ran successfully. Use this for audio, screen flash, etc.
On Interaction EndedInteractionLifecycleEventArgsPlayer walked away or the action finished. Use this to hide the prompt.

Writing a custom action (when you need code)

Use a subclass only when you need conditional availability or logic beyond a single method call.

Extend InteractableAction and add it as a component alongside InteractableTarget (which Unity adds automatically).

public class MyAction : InteractableAction
{
public override bool IsAvailable(InteractionContext context)
{
// Return false to gray out (or hide) this action in the HUD.
return /* your condition */;
}
public override void Execute(InteractionContext context)
{
// Your logic here.
base.Execute(context); // always call — fires OnExecuted
}
}

Reacting to events in code

When your UI manager needs to subscribe programmatically, use the C# events on InteractorBase directly:

private void OnEnable()
{
interactor.ShowActionsDiscovered += OnActionsDiscovered;
interactor.ActionSelectionChanged += OnSelectionChanged;
interactor.InteractionEnded += OnInteractionEnded;
}
private void OnDisable()
{
interactor.ShowActionsDiscovered -= OnActionsDiscovered;
interactor.ActionSelectionChanged -= OnSelectionChanged;
interactor.InteractionEnded -= OnInteractionEnded;
}
private void OnActionsDiscovered(ActionsDiscoveredEventArgs args)
{
// args.Actions — the visible action list; use it to populate your HUD
}
private void OnSelectionChanged(ActionSelectionChangedEventArgs args)
{
// args.Action — the newly selected action; highlight it in the HUD
}
private void OnInteractionEnded(InteractionLifecycleEventArgs args)
{
// Hide the HUD
}

Supporting multiple actions and cycling

An object can have any number of actions — component-based and SO-based coexist on the same InteractableTarget with no extra configuration. They are combined and sorted by Id automatically.

When more than one action is visible, the player can cycle between them:

// Call from your input handling code:
interactor.SelectNextAction();
interactor.SelectPreviousAction();

SelectNextAction() and SelectPreviousAction() skip unavailable actions automatically, so the selection always lands on something that can be executed. Each cycle fires ActionSelectionChanged so your HUD can highlight the new selection.


Two-step mode

Enable Interact To Show Actions on RaycastInteractor to change the flow:

Default (one-step)Two-step mode
Player aims at objectShowActionsDiscovered fires — HUD shows immediatelyActionsDiscovered fires — no HUD yet
Player presses interact (1st time)Executes the selected actionShowActionsDiscovered fires — HUD appears now
Player presses interact (2nd time)Executes the selected action

Use two-step mode when looking around is frequent (the crosshair skims over many objects) and you want to avoid the HUD flickering constantly. The player opts in to the interaction menu deliberately.

// You can also control two-step mode programmatically:
interactor.ShowInteractions(); // force-open the action menu
interactor.EndInteraction(); // cancel and clear the current target

Quick checklist

Before pressing Play:

  • RaycastInteractor is on the player — Player Camera is assigned.
  • The interactable object has a Collider and at least one InteractableAction component (which adds InteractableTarget automatically).
  • Your input code calls interactor.HandleInteraction() on the interact button.
  • Interactable Mask includes the layer your objects are on (defaults to Default — change to a dedicated layer in production for better performance).

Next steps

Action types in depth

Trade-offs between Component, SO, and Wrapper actions — and how to structure complex interactables.
Read the guide →

Event system

All events with their payload types, timing, and common HUD integration patterns.
Read the guide →

API Reference

Full member-level documentation for every class in the package.
Browse the API →