Skip to content

Game.Input.IProxyAction

Assembly:
Game

Namespace: Game.Input

Type: Interface

Base: None

Summary: Interface used by the input layer to provide a lightweight proxy/wrapper around Unity's InputSystem actions. Implementations typically forward calls to an underlying UnityEngine.InputSystem.InputAction (or similar) and expose a consistent set of checks and events that the rest of the game/mod code can query (pressed this frame, released this frame, current magnitude, read typed values, etc.). The interface also exposes an onInteraction event that reports InputActionPhase transitions so callers can react to action lifecycle events (started, performed, canceled).


Fields

  • None.
    Implementations may keep internal fields (InputAction references, frame tracking integers, cached magnitude, etc.), but the interface defines no fields itself.

Properties

  • public bool enabled { get; set; }
    Used to enable or disable the proxy. When disabled, implementations should typically ignore input callbacks and avoid invoking onInteraction. Useful for temporarily blocking input handling (UI modal, pause, etc.).

  • public event Action<ProxyAction, InputActionPhase> onInteraction
    Event invoked by the proxy whenever the underlying input action reports an interaction (started, performed, canceled). Subscribers receive the proxy instance and the InputActionPhase so they can react appropriately. (Note: this is an event member declared on the interface rather than a property; listed here for discoverability.)

Constructors

  • No constructors (interface).
    Concrete implementations will provide constructors to accept/initialize the underlying InputAction or other data they need.

Methods

  • bool WasPressedThisFrame()
    Return true if the action transitioned into a pressed/performed state during the current frame. Implementations commonly track the last frame index when a performed/start event happened and compare it with Time.frameCount.

  • bool WasReleasedThisFrame()
    Return true if the action transitioned into a released/canceled state during the current frame. Implementations commonly track the last frame index when a canceled event happened and compare it with Time.frameCount.

  • bool IsPressed()
    Return true if the action is currently in an active/pressed state (e.g., InputActionPhase.Performed). Use this to test continuous button hold.

  • bool IsInProgress()
    Return true if the action is currently in any in-progress phase (e.g., InputActionPhase.Started or Performed). Useful for actions that have a started/ongoing phase before performed.

  • float GetMagnitude()
    Return a floating-point representation of the action's magnitude (typical for analogue controls like triggers or axes). Implementations usually read the underlying value as float; if the action type is not float, they should convert or return an appropriate fallback (0f).

  • T ReadValue<T>() where T : struct
    Generic accessor to read the action's current value cast to a specific struct type. This should forward to the underlying InputAction.ReadValue() (or equivalent) and return the typed value.

Usage Example

using System;
using UnityEngine;
using UnityEngine.InputSystem;
using Game.Input; // assuming the interface is in this namespace

// A basic runtime implementation of IProxyAction that wraps a Unity InputAction.
public class ProxyAction : IProxyAction
{
    public bool enabled { get; set; } = true;
    public event Action<ProxyAction, InputActionPhase> onInteraction;

    private readonly InputAction m_Action;
    private int m_LastPressedFrame = -1;
    private int m_LastReleasedFrame = -1;

    public ProxyAction(InputAction action)
    {
        m_Action = action ?? throw new ArgumentNullException(nameof(action));
        m_Action.started += ctx => Handle(ctx);
        m_Action.performed += ctx => Handle(ctx);
        m_Action.canceled += ctx => Handle(ctx);
    }

    private void Handle(InputAction.CallbackContext ctx)
    {
        if (!enabled) return;

        if (ctx.phase == InputActionPhase.Performed)
            m_LastPressedFrame = Time.frameCount;
        else if (ctx.phase == InputActionPhase.Canceled)
            m_LastReleasedFrame = Time.frameCount;

        onInteraction?.Invoke(this, ctx.phase);
    }

    public bool WasPressedThisFrame() =>
        m_LastPressedFrame == Time.frameCount;

    public bool WasReleasedThisFrame() =>
        m_LastReleasedFrame == Time.frameCount;

    public bool IsPressed() =>
        m_Action != null && m_Action.phase == InputActionPhase.Performed;

    public bool IsInProgress() =>
        m_Action != null && (m_Action.phase == InputActionPhase.Started || m_Action.phase == InputActionPhase.Performed);

    public float GetMagnitude()
    {
        // Attempt to read as float; if that isn't appropriate for this action, return 0f.
        try
        {
            return m_Action.ReadValue<float>();
        }
        catch
        {
            return 0f;
        }
    }

    public T ReadValue<T>() where T : struct =>
        m_Action != null ? m_Action.ReadValue<T>() : default;
}

// Example usage:
// InputAction myAction = ... (created/loaded from InputActionAsset)
// var proxy = new ProxyAction(myAction);
// proxy.onInteraction += (p, phase) => Debug.Log($"Action phase: {phase}");
// if (proxy.WasPressedThisFrame()) { /* handle edge-on press */ }
// float val = proxy.GetMagnitude();