I am writing simple tiled map based game using LWJGL and Kotlin. I am testing out different collision detection algorithms and avoid using out of box solutions for personal reasons.

I figured out that running some kind of update loop, checking the presence of collisions between some entity and all the colliding objects may be too heavy in long run.

I want to know if some kind of collision detecting coroutine will be an appropriate idea. Since there be only one such coroutine that will only update the parameters that are sent to render loop, I should not be facing too many problems with race conditions. However, I am not sure that modern 2d games use similar approaches.

  • \$\begingroup\$ I'm not sure any performance gain would matter for 2d collision checking on today's hardware. \$\endgroup\$
    – Almo
    Oct 17, 2022 at 17:34
  • 1
    \$\begingroup\$ If your game has enough collision checking to be a performance concern then you should be using one of those out of box solutions. They have worried about optimizing so you don't have to. You might be worrying about optimization before you've even seen a problem that needs optimizing. Just make it without a coroutine first and it's very likely to not be too slow. \$\endgroup\$
    – Romen
    Oct 17, 2022 at 18:12

1 Answer 1


Probably not.

In a game, we usually don't want collisions to be processed eventually — we want them processed now. We have hard time constraints: we want to integrate all object motion forward one time step, detect and resolve collisions, all in time to render the next frame, so that we don't render two objects wedged halfway through each other while waiting for the detection and resolution thread to get back to us.

Similarly, ensuring the collision results are up-to-date this frame lets us begin playing impact sound effects immediately, so they don't sound delayed and disconnected from the objects' motion, as well as triggering gameplay state changes like dealing damage or spawning impact VFX.

So the usual "put it on its own thread and let it run asynchronously" strategy we might use for other processor-intensive work is not a great fit here. We'd need to almost immediately wait on the final results from that thread to do the next step of our gameplay updates anyway.

If the main thread is stuck waiting on these results before it can kick off rendering, then it might as well be the one computing those results. Just putting that work on another thread doesn't make it go faster, and you'd want to explore algorithmic optimizations instead.

That is, unless you have a large volume of other work that does not depend on collision info or object positions/orientations/velocities that you can schedule in between handing off to the collision-checking thread and retrieving the results. But often, most of the heavy work in a game depends on these kinds of transformation or movement properties. So if you have work that's the exception to this rule, it might make more sense to offload that work to the other thread, keeping the mainline dependency of object transformations simpler (and cache-resident).

Threading of bulk work in games is increasingly moving toward "job system" approaches, where instead of one long-lived thread devoted to each system/process, with queues or locks coordinating between them, we have a pool of general-purpose worker threads. As we process each system, we divide up its work into hundreds of work units to divide between the worker threads like a parallel-for, then wait on the results before farming out jobs for the next dependent system. This looks less like two threads running in parallel, and more like a braid or rope of sequential update phases that fans out wide for each phase and knots back together at dependency links between phases.

For instance, you could have a collision broadphase job that detects sectors of your world with potentially colliding objects, and divides them into islands. Then you can farm out each island to the worker thread pool to process, then collate the results for your subsequent gameplay update and rendering jobs.

Now you don't have one thread computing all your collisions before you can do the next step, but a group of threads each computing just a subset of your collisions, reducing the start-to-finish latency.

This strategy also scales better to hardware with different numbers of threads available, vs. having a single collision thread that runs just as slow on a 32-thread chip as on a 2-thread.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .