Quick answer: Store the RebindingOperation in a field. Call .Dispose() on cancel, complete, or scene exit. Operations are IDisposable; leaks cause input device handlers to accumulate.
A controls remapping screen lets the player rebind keys. After playing for a while, input feels laggy and you see hundreds of input-related allocations in the profiler. The rebind operations from earlier rebinds are still alive, still listening.
RebindingOperation Lifecycle
PerformInteractiveRebinding returns an IDisposable RebindingOperation. While alive, it intercepts input events to detect the next press. Multiple alive operations = multiple interceptors. Dispose releases the interception and frees handlers.
The Fix
private InputActionRebindingExtensions.RebindingOperation _rebindOp;
public void StartRebind(InputAction action, int bindingIndex)
{
// Cancel any previous
_rebindOp?.Cancel();
_rebindOp?.Dispose();
_rebindOp = action.PerformInteractiveRebinding(bindingIndex)
.OnComplete(op => {
SaveBindings();
op.Dispose();
_rebindOp = null;
})
.OnCancel(op => {
op.Dispose();
_rebindOp = null;
})
.Start();
}
void OnDestroy() {
_rebindOp?.Cancel();
_rebindOp?.Dispose();
}
Dispose in both OnComplete and OnCancel. Also dispose in OnDestroy in case the scene closes mid-rebind.
Action Must Be Disabled
action.Disable(); // before starting rebind
_rebindOp = action.PerformInteractiveRebinding(...)...
The action must be disabled while rebinding; otherwise existing bindings fire during the rebind input. Re-enable in OnComplete after applying the new binding.
Timeout
_rebindOp = action.PerformInteractiveRebinding(...)
.WithTimeout(5.0f)
.OnTimeout(op => {
op.Dispose();
ShowMessage("Rebind timed out");
})
...
Adds a 5-second timeout so players who back out via the OS menu don’t leave operations dangling.
Verifying
Profile after multiple rebind cycles. Memory usage and InputSystem handler count should stay flat. Cancel mid-rebind 20 times; no growth.
“RebindingOperation is IDisposable. Treat like a file handle — always close after use, even on cancel.”
Wrap rebind logic in a helper that handles cancel/complete/timeout disposal — reuse for every rebind UI without re-implementing leak-safe lifecycle.