Not really, it's a pretty trivial problem and one of the least concerns of game programming these days.
Not really, it's a pretty trivial problem and one of the least concerns of game programming these days.
In Starcraft II, when 2 Protoss players order one of their templars to move/cast a particular fatal spell to the other templar, then wait, you do not get the expected double kill. Instead, when they get in range of each other one templar casts the spell first, kill the other, and survives.
Which templar lives and which dies depends on the order the units are processed in the frame —arguably an implementation detail. To the players, this is just plain unfair. Not a deal breaker for a hosts of reasons, but still no good.
It's not game breaking, but players noticed this.
To avoid such problem with marines shooting (this would be game-breaking, because marines make up bulk of terran armies for most of the game) - there is miniscule random factor added to delay between shots for each marine.
If it was important enough - they would fix the high templar/ghost problem the same way.
BTW in e-sport games (like Starcraft) - finding such bugs and abusing them creatively is part of game. For example mineral-walking is legitimate techinque to micromanage your workers, used even in low-level matches, and it's caused by workaround of bug in Starcraft 1.
- Unit1 kills unit2
- Unit2 kills unit1
If you double buffer your actions properly, both unit will be dead at frame N+1. If however you modify your data in place, this may happen: 1. Unit1 kills unit2 => delete unit 2
2. Unit2 no longer exists. Unit1 lives.
Or, this may happen: 1. Unit2 kills unit1 => delete unit1
2. Unit1 no longer exists. Oops.
Oops.What definitely does not happen is the double kill. StarcraftII can live with that, but other games, like Frozen Synapse, would be broken.
In that case you take all the attacks, computes the damages, apply them and prune the dead.
There are a lot of problems with global state in games, but entity values are not one of them, mostly. Problems do crop up but you just deal when they do.
If your actors has a single 'update' method, the first actor would check for collisions and move before any other actors had a chance to do anything. This gives certain actors preferential treatment in movement.
Of course, you could instead plan out the dependencies better; do all collision detection before all physics response. But this is just a different way to look at 'immutability'
There may be exceptions to this; it is not a subject I keep current with.
eg: instead of:
foreach actor(find collisions -> find response -> do movement)
do: foreach actor(find collisions) ->
foreach actor(find response) ->
foreach actor(do movement)
That way you may modify the primary data structure directly in the 'do movement' response without any conceptual 'data races'. It really just off loads the information lost from 'mutability' to the secondary data structures of collision lists and the like.