Extending with code

Everything is in the RomanoAssets.InteractionKit namespace (editor tools in RomanoAssets.InteractionKit.Editor).

Events #

interactable.Interacted += (target, interactor) => Debug.Log($"{interactor.name} used {target.name}");
interactable.Denied += (target, interactor, check) => Debug.Log("Refused: " + check.Reason);
interactable.StateChanged += target => Save();
interactor.FocusChanged += (who, focus) => Highlight(focus);

The same events are on the Interactable in the Inspector (On Interacted, On Denied...) for no-code use.

Use an object from code #

var result = interactable.Request(interactor);              // the normal path (goes to the host in multiplayer)
var forced = interactable.ExecuteAuthoritative(null, false); // apply now, skipping the range check (cut scenes, triggers)
var check = interactable.Evaluate(interactor, true);        // would it work? check.Allowed, check.Reason
interactor.SetExternalInput(true);                          // press the interact button for AI or tests

Your own behaviour #

public sealed class LightSwitch : InteractionBehaviour
{
    [SerializeField] private Light lamp;
    public override string Verb => lamp.enabled ? "Turn Off" : "Turn On";
    public override int StateValue => lamp.enabled ? 1 : 0;
    public override void ApplyState(int value, bool instant) => lamp.enabled = value != 0;
    public override void Apply(Interactor interactor) { lamp.enabled = !lamp.enabled; NotifyStateChanged(); }
}

Put it next to an Interactable. StateValue / ApplyState make it save and network correctly.

Your own rule #

Derive from InteractionCondition and return InteractionCheck.Allow or InteractionCheck.Block(InteractionBlocker.Condition, "Needs power", this) from Evaluate. The reason appears in the prompt and the debug overlay.

Saving and loading #

Each object's state is a short list of numbers:

InteractableSnapshot snapshot = interactable.CaptureSnapshot(); // [Serializable]: JSON or any save system
interactable.RestoreSnapshot(snapshot, instant: true);

Your own input #

Derive from InteractionInputSource (the interact button, plus the key and gamepad button shown in prompts), or implement IInteractionInputBackend and call InteractionInput.SetBackend to change how keys and buttons are read.

Your own prompt #

Derive from InteractionPromptPresenter: it works out the text, button, device, fade and hold progress every frame (View); you only draw it.

Something unclear or wrong? Tell us · Get help