Here's a problem that's sort of typical of the bugs that can crop up during AI programming and is a good example of why producing reliable AI can be a time intensive process.
In (TU2) levels where one team has a presence in the form of buildings and the opposite team is 'invading', one of the units that will typically be airlifted in by the invaders is a 'sapper'. These units like to sidle up to an enemy building and 'drill' into the building until the structure's shield level is depleted. Once a building has been destroyed, the sapper should move on to the next.
I had this working quite well in a test level where there were a few buildings and one sapper. However as soon as I incorporated multiple sappers into a level that had many units and buildings, the sappers were destroying one building and then staying put - not moving on to their next target. Why?
Note: This is bare bones - no particle fx or bloom etc..
I wracked my brains. Why were the sappers not being deployed after their first building demolition? Each team has a list of 'sightings' for which an unseen 'commander'periodically deploys appropriate units. If flags were not being reset that could account for sappers not doing what they should. I set various debug points and stepped through my code. This was time consuming in itself as it needed the game to run for a period of time before the proper conditions were available to check.
No - it appeared the code was picking up that the sappers were coming free for new orders after destroying a building.
So what could it be?
I suddenly twigged. Each level is basically an underlying grid of squares with each square set to either passable or non-passable. It's a basic system and the game uses A* to calculate best routes for vehicles through the level.
When a building is placed, the area of squares it occupies are set impassable - and actors should find their way around the buildings. If a building is destroyed, the squares it occupies are set back to passable. Sappers are a bit different in that once they're in position, they should move onto impassable squares (towards the building's centre) in order to come in contact with the building and start 'drilling'.
So what was happening? Once a sapper had destroyed a building, its area was being returned to passable and the sapper should have been able to go on its way!
I checked by adding in some visible blocks representing non-passable areas. The problem became visible at once. It appeared that occasionally, when a building was destroyed, an outside ring of squares would be left as 'impassable'. This would result in the sapper being 'imprisoned' within this ring and not able to calculate a route out. So it would stay put.
This discrepancy between area calculation appears to be down to float errors. I've since solved it by doing an extra check - but it's emblematic of the kind of snares that can trip up what seems like a straight-forward feature implementation.