So gist of my problem is I have "Entities" (Kinematic Body 2Ds) that occupy a grid of "Tiles" (Area 2Ds) - think a custom TileMap. I move these entities via the physicsprocess(), but I move them in discrete steps (from one tile to the next, think a chess board) so I don't apply any velocity to them (which from what I understand is a no-no). I have an issue where every so often when two entities try to move in the exact same frame they can occupy the same tile. I've tried numerous ways to resolve this. I've double checked that the tile is collision masked for entities and vise versa.
in the physicsprocess() of the entity if it is in a moving state it will get a path to follow then attempt to move one tile during that frame. in attempt to make sure two entities don't occupy the same tile i've made locks for the tile.
var _lock := Mutex.new()
if _lock.try_lock() == OK:
_lockedForEntity = e
return _lockedForEntity == e
_lockedForEntity = null
This is (modified code but essentially what executes, entities interface with a board which interfaces with a tile) what the entity attempts to execute during physicsprocess() if it is in the moving state:
self.position = targetTile.position
_canMove = false
I left the movetimer in there to show that entities are locked out of movement for a period of time after moving so they don't try to move every frame.
From what I gather if there is a situation where two entities want to move to the same unoccupied tile: isEmpty() will be true - and that's where i get confused because:
- the Mutex should ensure thread safe, single access locking for the tile
- i even double check to make sure it's locked for the correct entity before attempting to move.
I've tried the brute force solution of:
yield(get_tree().create_timer(rand_range(0.05, 0.1), "timeout")
at the start of lockTileForEntity(e), until i realized that yielding drops the thread out of the function back up the call stack. This definitely cut down on the occurrences of two entities occupying the same tile, but didn't eliminate it all together.
I'm new to game development and godot so i'm definitely open to proper solutions for this issue.
Thank you for your help!