circle-exclamation
STILL WORKING ON DOCS

handModular Interaction System

A powerful, networked, mod-first interaction framework designed for flexibility and depth — far beyond simple "press E to use".

Every object that can be interacted with implements the IInteractable interface. The system handles detection, UI presentation, input forwarding, physics carrying, cancellation logic, and networking — all in one unified pipeline.

Core Components & Flow

  1. Detection Phase (Client-side)

    • PlayerInteraction performs a raycast from the camera every frame (max interactRange = 3 m by default)

    • Only objects on the interactLayer are considered

    • If a valid IInteractable is hit → UI panel appears with object name + list of options

  2. Option Selection & Activation

    • Player can scroll (mouse wheel) to highlight different options

    • Options are provided dynamically by the object via GetOptions()

    • Two main types:

      • Instant (RequiresHold = false) → triggered on single press (OnPress)

      • Hold (RequiresHold = true) → supports OnHoldStart / OnHoldUpdate / OnHoldReleased / OnHoldCanceled

  3. Interaction Packet — the heart of the system Every interaction sends a rich InteractionPacket to the server:

    public struct InteractionPacket
    {
        public string ActionTag;           // "OnPress", "OnHoldStart", "OnHoldUpdate", etc.
        public float HoldDuration;         // how long the hold has been active (seconds)
        public List<KeyCarryingData> Inputs; // all relevant inputs at that moment
    }

    KeyCarryingData contains:

    • Button states (CustomI_XXX keys that are pressed)

    • Press order (stack index — first pressed = highest priority)

    • Mouse delta (CustomI_MouseVector2 → Vector2)

    • Other analog values if needed

    → This packet lets the object know exactly what the player is doing right now.

  4. Server-side Execution

    • Client → CmdInteract(NetworkObject target, optionId, packet)

    • Server → finds IInteractable on the target → calls OnInteract(playerGameObject, optionId, packet)

Important Mechanics & Safety Features

Feature
Description
Default / Typical Value

Interaction Range

Max distance for raycast detection

3.0 m

Hold Distance Limit

While holding, if player moves too far → interaction is auto-canceled

4.5 m

Distance Check Frequency

Checked every frame on client during hold

Forced Termination

Object can call BreakInteractionFromObject() to kick player out of hold (e.g. after throw)

Server → ObserversRpc → client

Cancellation Reasons

Too far / object destroyed / external force / invalid state

Client shows debug log

Hold Cancellation Tags

OnHoldCanceled (abrupt end) vs OnHoldReleased (normal drop)

Used for different reset logic

Input Forwarding

All CustomI_ actions + mouse delta are sent every frame during OnHoldUpdate

Priority stack preserved

Real Example: Forced End + Distance Break

Why This Level of Control Matters

  • Objects can reject interaction (return empty GetOptions list)

  • Objects can force-stop holding (e.g. item breaks, explodes, gets stolen)

  • Players can't abuse range (auto-drop prevents flying objects forever)

  • Modders can read any custom input without changing core scripts

  • Debugging is easier (hold timer, input stack, distance shown in OnGUI debug overlay)

This system gives you both player freedom and server authority, while staying extremely modder-friendly.

Last updated