Hi there,
Im new to UniTask and need help writing the right code for a debounce method
In my code im using bool but ideally i want to have a “void” if possible but i dont know.
Please advise
public async UniTaskVoid DebounceMethod()
{
if (taskCompletionSource != null)
{
taskCompletionSource.TrySetCanceled();
taskCompletionSource = null;
}
taskCompletionSource = AutoResetUniTaskCompletionSource<bool>.Create();
await UniTask.WaitForSeconds(delayInSeconds);
taskCompletionSource.TrySetResult(true);
taskCompletionSource = null;
onDefaultEvent(this);
}
What are you debouncing? Just set a float for whatever the debounce time is and count it down.
Cooldown timers, gun bullet intervals, shot spacing, rate of fire:
This is my implementation using UniTask
using Cysharp.Threading.Tasks;
using System;
using System.Threading;
public class Debouncer
{
private readonly float debounceTime;
private readonly Action action;
private CancellationTokenSource cts;
public Debouncer(float ms, Action action)
{
this.debounceTime = ms;
this.action = action;
}
public void Call()
{
cts?.Cancel();
cts = new CancellationTokenSource();
DebounceCall(cts.Token).Forget();
}
private async UniTask DebounceCall(CancellationToken cancellationToken)
{
await UniTask.Delay(TimeSpan.FromMilliseconds(debounceTime), cancellationToken: cancellationToken);
if (!cancellationToken.IsCancellationRequested)
{
action();
}
}
}
And how to use it
using UnityEngine;
public class UniTaskDebounceExample : MonoBehaviour
{
private Debouncer debouncer;
private void Start()
{
debouncer = new Debouncer(500, () => Debug.Log("Hello world!"));
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
debouncer.Call();
}
}
}
I am sure there are fancier and more performance approaches but at least this gets the job done
Nice one 
I have just two little nitpicks:
There’s no need to handle cancellation a second time manually, if you’re already passing the token to UniTask.Delay
:
private async UniTask DebounceCall(CancellationToken cancellationToken)
{
await UniTask.Delay(debounceTime, cancellationToken: cancellationToken);
action();
}
decounceTime
could be a TimeSpan
(or at least an int
) so that it’s not so ambiguous whether it’s in seconds or milliseconds:
public Debouncer(int ms, Action action)
{
debounceTime = TimeSpan.FromMilliseconds(ms);
this.action = action;
}
Seeing float
in Unity makes me think seconds, and it’s a weird conversion to make, when TimeSpan.FromMilliseconds
only accepts a double
.
1 Like