Skip to content

Instantly share code, notes, and snippets.

@ashrafmajdee
Last active August 14, 2023 05:03
Show Gist options
  • Save ashrafmajdee/292b2b12001373bc3d51143b005b99a3 to your computer and use it in GitHub Desktop.
Save ashrafmajdee/292b2b12001373bc3d51143b005b99a3 to your computer and use it in GitHub Desktop.
Unity input system interaction to detect if opposing keys like left/right is pressed simultaneously and delay the interaction to see if one of the key's is released. One use cases is, if using a state machine with Input magnitude for character movement, character can keep moving from one direction to the opposite without going to 'Idle' state.
using UnityEngine;
using UnityEngine.InputSystem;
#if UNITY_EDITOR
[UnityEditor.InitializeOnLoad]
#endif
public class OpposingKeyPressInteraction : IInputInteraction
{
public float HoldDuration = 0.15f;
private InputInteractionContext ctx;
private float _timer;
#if UNITY_EDITOR
static OpposingKeyPressInteraction()
{
Initialize();
}
#endif
[RuntimeInitializeOnLoadMethod]
static void Initialize()
{
InputSystem.RegisterInteraction<OpposingKeyPressInteraction>();
}
public void Process(ref InputInteractionContext context)
{
ctx = context;
if (ctx.control.IsPressed() && context.ReadValue<Vector2>().magnitude == 0)
{
_timer = HoldDuration;
InputSystem.onAfterUpdate -= OnUpdate; // Safeguard for duplicate registrations
InputSystem.onAfterUpdate += OnUpdate;
return;
}
if (ctx.phase == InputActionPhase.Waiting)
{
context.PerformedAndStayStarted();
return;
}
if (ctx.phase == InputActionPhase.Started)
{
context.Performed();
return;
}
}
private void OnUpdate()
{
if (_timer > 0)
{
_timer -= Time.deltaTime;
if (ctx.ReadValue<Vector2>().magnitude != 0)
{
ctx.PerformedAndStayStarted();
InputSystem.onAfterUpdate -= OnUpdate;
_timer = 0;
}
}
else
{
if (!ctx.ControlIsActuated())
{
ctx.Canceled();
}
InputSystem.onAfterUpdate -= OnUpdate;
}
}
public void Reset()
{
InputSystem.onAfterUpdate -= OnUpdate;
_timer = HoldDuration;
if (!ctx.ControlIsActuated() && (ctx.phase == InputActionPhase.Started || ctx.phase == InputActionPhase.Performed))
{
ctx.Canceled();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment