- Home /
Grid Based Movement System AI freezing?
In this code the AI will take a position in a queue to decide which player to attack, then decide the closest player and then decide the one with the lowest health, use path finding to find the shortest route there(Some tiles cost more action points to move through than others), then move towards the player it has decided to attack. But once the AI starts to make its move it freezes in place, and its position queue reverts to ZERO in the inspector. If i manually change its position queue back to 1 it will finish its move but its not just the one AI player, they all will sometimes act right and do what its supposed to do then sometimes in mid move it just freezes for no reason.. A short code snippet from my AIPlayer class. I have gone over it multiple times. It just needs fresh eyes, and any input you can give is helpful. thank you.
public override void Update () {
if(GameManager.instance.players[GameManager.instance.currentPlayerIndex] == this) { //If this is current player
transform.renderer.material.color = Color.green; //Turn its material to green
} else {
transform.renderer.material.color = Color.white; //If not current player, turn its material to white
}
base.Update();
}
public override void TurnUpdate ()
{
if (positionQueue.Count > 0) { //If the position Queue is greater than 0
transform.position += (positionQueue[0] - transform.position).normalized * moveSpeed * Time.deltaTime;
if (Vector3.Distance(positionQueue[0], transform.position) <= 0.1f) {
transform.position = positionQueue[0];
positionQueue.RemoveAt(0);
if (positionQueue.Count == 0) { //if position queue count is at zero
actionPoints--; //spend action points
}
}
} else {
//priority queue
List<Tile> attacktilesInRange = TileHighlight.FindHighlight(GameManager.instance.map[(int)gridPosition.x][(int)gridPosition.y], attackRange, true);
//List<Tile> movementToAttackTilesInRange = TileHighlight.FindHighlight(GameManager.instance.map[(int)gridPosition.x][(int)gridPosition.y], movementPerActionPoint + attackRange);
List<Tile> movementTilesInRange = TileHighlight.FindHighlight(GameManager.instance.map[(int)gridPosition.x][(int)gridPosition.y], movementPerActionPoint + 1000);
//attack if in range and with lowest HP
if (attacktilesInRange.Where(x => GameManager.instance.players.Where (y => y.GetType() != typeof(AIPlayer) && y.HP > 0 && y != this && y.gridPosition == x.gridPosition).Count() > 0).Count () > 0) {
var opponentsInRange = attacktilesInRange.Select(x => GameManager.instance.players.Where (y => y.GetType() != typeof(AIPlayer) && y.HP > 0 && y != this && y.gridPosition == x.gridPosition).Count () > 0 ? GameManager.instance.players.Where(y => y.gridPosition == x.gridPosition).First() : null).ToList();
Player opponent = opponentsInRange.OrderBy (x => x != null ? -x.HP : 1000).First ();
GameManager.instance.removeTileHighlights(); //remove highlighted tiles once a move destination has been reached
moving = false; //make moving false
attacking = true; //make attacking true
GameManager.instance.highlightTilesAt(gridPosition, Color.red, attackRange); //highlight in red the tiles player can attack based on attack range
GameManager.instance.attackWithCurrentPlayer(GameManager.instance.map[(int)opponent.gridPosition.x][(int)opponent.gridPosition.y]); //attack the target in the tile that is chose
}
//move toward nearest opponent
else if (!moving && movementTilesInRange.Where(x => GameManager.instance.players.Where (y => y.GetType() != typeof(AIPlayer) && y.HP > 0 && y != this && y.gridPosition == x.gridPosition).Count() > 0).Count () > 0) {
var opponentsInRange = movementTilesInRange.Select(x => GameManager.instance.players.Where (y => y.GetType() != typeof(AIPlayer) && y.HP > 0 && y != this && y.gridPosition == x.gridPosition).Count () > 0 ? GameManager.instance.players.Where(y => y.gridPosition == x.gridPosition).First() : null).ToList();
Player opponent = opponentsInRange.OrderBy (x => x != null ? -x.HP : 1000).ThenBy (x => x != null ? TilePathFinder.FindPath(GameManager.instance.map[(int)gridPosition.x][(int)gridPosition.y],GameManager.instance.map[(int)x.gridPosition.x][(int)x.gridPosition.y]).Count() : 1000).First ();
GameManager.instance.removeTileHighlights();
moving = true;
attacking = false;
GameManager.instance.highlightTilesAt(gridPosition, Color.blue, movementPerActionPoint, false);
List<Tile> path = TilePathFinder.FindPath (GameManager.instance.map[(int)gridPosition.x][(int)gridPosition.y],GameManager.instance.map[(int)opponent.gridPosition.x][(int)opponent.gridPosition.y], GameManager.instance.players.Where(x => x.gridPosition != gridPosition && x.gridPosition != opponent.gridPosition).Select(x => x.gridPosition).ToArray());
if (path.Count() > 1) {
List<Tile> actualMovement = TileHighlight.FindHighlight(GameManager.instance.map[(int)gridPosition.x][(int)gridPosition.y], movementPerActionPoint, GameManager.instance.players.Where(x => x.gridPosition != gridPosition).Select(x => x.gridPosition).ToArray());
path.Reverse();
if (path.Where(x => actualMovement.Contains(x)).Count() > 0) GameManager.instance.moveCurrentPlayer(path.Where (x => actualMovement.Contains(x)).First());
}
}
the only thing I could recommend is adding Deb.Log lines to see what parts of the script cause problems.
Answer by SnStarr · Jan 22, 2015 at 07:54 PM
Actually after several Debug.Log and testing on several different devices and PCs I can say that with the code unchanged as it stands, the problem only comes up on low end PCs and older mobile devices. My Gaming rig, my office Computer and my new Windows Phone all have no problems at all. It must be a memory or graphics card problem. Can't for the life of me figure it out, but as the code works with no problems on higher end devices and PCs, I am not gonna change the code.