Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Phase Based Multi Threading

Discussion in 'Scripting' started by zh99998, Sep 14, 2020.

  1. zh99998

    zh99998

    Joined:
    Mar 2, 2020
    Posts:
    17
    I got a really simple idea to do multi thread logic. It's too simple so I think there must be a old normal design pattern. but I can't find it.

    Let's say I'm building a warcraft-like RTS game, where there are thousands of units and bullets.
    each logic frame(trigger by FixedUpdate or Network) will do these updates:
    update each bullet, check it's hit unit, take unit HP or Die.
    update each buffs and skills of each unit, decease timer, change unit fields, search nearby units.
    update each unit action, move, attack, and more logic, managed by a state machine.
    update physics, collision and sync transform.

    we can see each function will try to interactive with other unit, which makes multi threading corruptable.
    but we can split write ownership of each field with each phase.

    if a field mark as readonly, then everyone can get it but not set it.
    if a field mark as readwrite, then only self unit can get/set it.
    if there are multi job on same unit, they will execuate serially.

    for example, I can divide my logic into 2 phases
    phase1 will do most of logic, most of public fields are marked readonly in this phase.
    if someone need to change a readonly field, save a job. (the "job" is just a function call, not unity job.)
    phase2 most of fields are marked readwrite, and will run every job.


    unit position and HP is readonly in phase 1
    a heal skill that will checks nearby units which not full HP, and make it full. it can do search immediatly, but can't change unit HP, insdad, it saves a job that marks will heal this unit.

    velocity of rigibody is readwrite, when unit decide to move, it could set velocity of rigibody immediately, since there is no skill try to access other unit's velocity.

    in phase 2. HP is writable, so heal jobs run.
    in physics phase, every unit moves by marked velocity, and calculate collision, then sync transform.

    new LogicUpdate method looks like this:
    update phase1 with multi threads
    wait for all threads done
    update phase2 with multi threads
    wait for all threads done
    update physics and sync transform.

    it's really simple, just mark each field ro or rw in each phase. everything will done graceful.
    No ECS, no DOTS, also no traditional mutex. just keep intuitive OOP and GameObject-MonoBahavior model.
    It's even deterministic which can use time-based frame sync on network. (without 3D physics. In my game I'm using 2D physics and remap back to 3d space).

    I want to confirm that:
    does this pattern has a name?
    does it achievable in Unity ?
    if answer for #2 is no. does it works in other language or engine?
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    Is there is one heal-thread that heals all units that are marked for healing, or that there is one heal-thread per unit that's marked for healing? Ideally you'd want to have a group of precreated worker threads which work through these jobs as you call them. If not you effectively throw multithreading out of the window in this step, or run into the same problems of having multiple threads (at least heal and damage) writing to the same field. Doing so sequentially with multiple worker threads would of course get rid of this problem.. but at that point you effectively recreated some of the aspects of DOTS in an less efficient way.

    So if you really need to handle thousands of entities and bullets and whatnot, take a look at DOTS. It will most likely be severely faster than any solution you may come up with. Which is not meant in a rude way, its just insanely fast. For most project i'd say the performance gain is not necessary and thus the time cost to get into it and deal with the lack of documentation is not worth it, but for games with a high degree of required parallelization, such as RTS of simulation, it's definitely worth the effort. On most workloads you can expect a speedup of factor 10-100x. It also has some support for running things like networking and physics off the main Unity thread, which is useful since most of the Unity API by default only works on the main Unity thread.
     
    Last edited: Sep 14, 2020