Does unitask/async make sense over simple deltatime timer for cooldowns etc

Trying to wrap my head around when should i use async/await in game dev context.

I wouldn’t use it for cooldowns. Async is generally for processes that can take some indeterminate amount of time, where you don’t want it to lock up the program. Namely file loading, reading, writing, etc. Which is why you see it for systems like addressables, and for scene loading.

Using async for cooldowns would just be massively over-complicating something otherwise simple.

Thanks @spiney199 for sharing the beneficial information. I also face this problem.

Agreed. Unfortunately this is common, especially with async-happy or coroutine-happy tutorial makers.

Cooldown timers, gun bullet intervals, shot spacing, rate of fire:

NEVER NEVER NEVER use coroutines for a cooldown. It is never appropriate.

1 Like

I’m a bit puzzled… cooldowns are a common behavior. Why would folks write unique code for every situation? I’m looking at it like an IRL alarm clock.

Why not a CoolDown service that other code can register with. An event is fired when the cooldown time they requested is reached.

Yes the code that processes the time is the question here but again I’m surprised (a bit) that there aren’t a half-dozen “cool down” libraries.

Writing libraries is about adding value: you write a library to capture a significant piece of work that has well defined inputs and well defined outputs.

Cooldown timers are trivial. Librarifying them doesn’t help.

Plus there’s ten billion different options / variations, etc. Here’s a few:

  • can it be reset mid-way, before it expires? Now your library needs an extra call!
  • should an attempt to reset mid-way before it expires be ignored? Now your library needs two calls or a call with a parameter
  • should an attempt to reset it midway be cause for alarm, eg, log an error and go investigate why something higher up in the application chain could even possibly have attempted this?
  • does it stop counting down under certain conditions, eg, you hit reload on your pistol, then stuff it into your pocket… should the timer continue while in your pocket? Hm, could be different depending on the game.
  • does the cooldown need to be updated to a UI widget to show how close to cooldown it is? Now you need a call to set a callback, register an event, or inspect the value
  • does something cause the cooldown interval to change (Eg, a buff or debuff)? Now you need a buff interface!

Again… write libraries where you add value. Otherwise you end up with a mass of librarified generic code and you don’t DARE change any of it because by now you have forgotten “Gee does this library even allow resetting before it is expired?” etc

1 Like

Perhaps my use of the term library was off the mark and I should have written template or guide. I was shocked to learn that there are 10 billion different options.

I any case I will continue to write whatever it is that I do with my custom logger, API calls to APIs I’ve written, etc. If it needs to reset midway I’ll spend the $50,000 and spend the 3 years needed to adjust it.

Thanks for providing solution. Appreciated.

I’m necroing this thread out of annoyance. You are completely correct and Kurt is just wrong. Unity has invoke and invoke repeat, but they aren’t type safe and don’t return any value for cancelation handling, making them a very poor tool for sloppy disgusting programming. They should remove or replace it imo.

In the meantime, I recommend writing a simple class that replaces Invoke and Invoke Repeat with a type safe variation, cancellability, and an InvokeDebounce method to prevent overlap if needed. Basically, fix the revolting invoke system. You can wrap in a generic base-class monobehavior to inherit its functionality, and/or generalize as a C# script that can utilize a monobehavior surrogate to run the callbacks. Static utility scripts can also be a good resource, but not for time based instanced behaviors.

You can always very easily extend tools to meet specific needs by adding in methods of the same name with new parameters, or just adding in new method altogether. Timers carry a bunch of boilerplate, but are extremely generalizable. Doing so makes things way more maintainable, not less. I honestly think Kurt just doesn’t understand how to write or utilize tools, and is giving very bad advice. I’ve used and built on the same tools for a decade, and its been immensely helpful.

All of his specific use cases can utilize the same simple timer script, or can build on it. Need to adjust the time frame or rate of time? Add a method to the class that cancels the timer callback, returns the time left value, and creates a replacement callback with new parameters. Need to return a value at the end of the timer? Create a version of the delegate that returns however many generic types you need. Highly extendable, highly flexible, type safe, boilplate and auto cancel wrapped in a mono base class, and no need to go back and change anything. This is exactly the type of stuff C# was designed for. Use it.

1 Like

Use async/await anytime you need to wait for something that takes time (network, disk, long computation) but want the game to remain responsive. Most of the use cases come from I/O operations, writing and reading.

Loading assets from disk or downloading data from a server (like player stats, game levels, or remote configurations). You don’t want the game to freeze while waiting.

Much appreciated. Developers for some reason and perhaps people in general often get lost on the minutia. If “trivial” was the working criterion there wouldn’t be a String.ToUpper or built in sorting routines.

I haven’t found a place where “solutions” are shared and exchanged. Something between a github repo and just posting a message in a thread. I suspect something exists but I haven’t been able to find it.