Well, I’m stuck on mine. Since this is, at heart, your tech, I’ll share it.
It’s a two piece system so far - the “Map” program, which lives on your actual terrain, and the AI program which executes the AI. These were perhaps too simple tests; in hindsight, this might not be so great for pathfinding, but more of managing high-level objectives like defending a particular spot. Anyways, here they are:
TacticMappedAI.js:
class NodeAction
{
var actionString : String;
var nodeColor : Color;
}
var speed : float;
var aiActions : NodeAction[];
private var tacticMap : TacticMap;
private var mapWidth : int;
private var mapHeight : int;
private var moveDirection : Vector3;
private var mapLocation : Vector2;
private var oldIndex : int;
private var mapIndex : int;
private var aiCommand = new Array();
function Start()
{
// Start by finding a tactic map. Wring some
// good info out of it.
tacticMap = FindObjectOfType( TacticMap );
mapWidth = tacticMap.map.width;
mapHeight = tacticMap.map.height;
// "Unfurl" the tactical map by converting the map's
// pixel colors into an array of AI command strings.
var mapColors : Color[] = tacticMap.map.GetPixels( 0 );
for( var point : Color in mapColors )
{
// Read the color, then match it to an index
// in the aiActions array. If it matches,
// assign the command to the AI array.
for( var action : NodeAction in aiActions )
{
if( point == action.nodeColor )
{
aiCommand.Add( action.actionString );
break;
}
}
}
// Pre-set the move direction, initialize the transition
// recognition.
moveDirection = Vector3.forward;
CalculatePosition();
mapIndex = ConvertPointToLinear( mapLocation, mapWidth );
oldIndex = mapIndex;
// That's all for preparation. See you in FixedUpdate!
}
function FixedUpdate()
{
CalculatePosition();
mapIndex = ConvertPointToLinear( mapLocation, mapWidth );
if( mapIndex != oldIndex )
{
InterpretAction( aiCommand[mapIndex] );
oldIndex = mapIndex;
}
transform.Translate( moveDirection * speed * Time.deltaTime );
}
function InterpretAction( actionString : String ) : void
// There's nothing for it. This function has to be
// hard-coded by the end-user or their programmer.
//
// In this example, InterpretAction() only handles
// the alteration to moveDirection. In your game,
// you may want this to have links to firing weapons,
// changing pursuit targets, or other actions.
{
//Debug.Log( "Acting on instruction: " + actionString );
if( actionString == "Go Straight" )
{
transform.Rotate( 0,0,0 );
}
if( actionString == "Go Backward" )
{
transform.Rotate( 0,180,0 );
}
if( actionString == "Go Left" )
{
transform.Rotate( 0,90, 0 );
}
if( actionString == "Go Right" )
{
transform.Rotate( 0,-90, 0 );
}
}
function CalculatePosition() : void
// We want to find (0,0), so we take the local dimensions,
// and divide by the tactical map dimensions to derive a
// coordinate system.
{
var mapDims : Vector3 = tacticMap.transform.localScale;
var mapCenter : Vector2 = tacticMap.CenterCoordinate();
var mapX : int;
var mapY : int;
// Calculate the map position...
mapX = transform.position.x - tacticMap.transform.position.x;
mapX /= mapDims.x;
mapX /= tacticMap.trueDimensions.x;
mapX += mapCenter.x;
mapY = transform.position.z - tacticMap.transform.position.z;
mapY /= mapDims.y;
mapX /= tacticMap.trueDimensions.y;
mapY += mapCenter.y;
mapLocation = Vector2( mapX,mapY );
Debug.Log( "I am at (" + mapLocation.x + ", " + mapLocation.y + ")" );
}
function ConvertPointToLinear( coords : Vector2, width : int ) : int
{
return coords.x + ( coords.y * width );
}
TacticMap.js:
var map : Texture2D;
var trueDimensions : Vector2;
var centerOrigin : boolean = true;
var debugMode : boolean = false;
private var mat : Material;
private var originCoord : Vector2;
function Start()
{
// This just shows the tactical map on the mesh.
if( debugMode )
{
mat = renderer.material;
mat.mainTexture = map;
}
// Derive the real origin offset. We do this by
// looking at the width and height of the map
// image.
if( centerOrigin )
{
originCoord = Vector2( ( map.width / 2 ), ( map.height / 2 ) );
}
else
{
originCoord = Vector2.zero;
}
}
function CenterCoordinate() : Vector2
{
return originCoord;
}