tactical character behaviour?

Hi everybody,
I was trying to write a code for tactical behaviour like finding cover and moving in a squad, finding and joining a new group leader, etc…
So I have some trouble with the part of the code that should let the character find a group leader, so if anyone got an idea, please let me know :slight_smile:

This is the code:

var speed = 3.6;
var runSp = 2.0;
var strafe = 2.0;
private var actStr = 0.0;
var actSp = 3.6;
var rotDamp = 6.0;
var precision = 0.4;
var lead : boolean = false;
var leader : Squad1;
var leaders : Squad1[];
var maxLdrDist = 25.0;
var followPos : Transform[];
var followBool : Transform[];
var fullSquad : boolean = false;
private var num : int = 0;
var pos : Transform;
// Oos = Out Of Sight...
var Oos : boolean = false;
var target : Transform;

function FixedUpdate () {
	if (lead == true) {
		for (var posi : Transform in followBool) {
			if (posi != null) {
				fullSquad = true;
			}
			else {
				fullSquad = false;
			}
		}
	}
	if (lead == false  leader == null) {
		var ldrs = FindObjectsOfType(Squad1);
		for (var i : int; i<leaders.length; i++) {
			if (ldrs[i] != null  ldrs[i].lead == true) {
				leaders[i] = ldrs[i];
			}
		}
		for (var ldr : Squad1 in leaders) {
			if (ldr != null  ldr != GetComponent(Squad1)  ldr.lead == true  ldr.fullSquad == false  Vector3.Distance(transform.position,ldr.transform.position) < maxLdrDist) {
				leader = ldr;
			}
		}
	}
	if (lead == false  leader != null  pos == null) {
		if (num < leader.followPos.length) {
			if (leader.followBool[num] == null) {
				Debug.Log(transform.name + ": Squadleader found!");
				pos = leader.followPos[num];
				leader.followBool[num] = leader.followPos[num];
				num = 0;
			}
			if (leader.followBool[num] != null) {
				Debug.Log(transform.name + ": Still searching...");
				num += 1;
			}
		}
		else {
			leader = GetComponent(Squad1);
			FindLeader();
			pos = null;
			num = 0;
			lead = true;
		}
	}
	if (pos != null  lead == false) {
		//var hit : RaycastHit;
		//if (Physics.Linecast(transform.position, pos.position, hit)) {
		//	if (hit.transform != null) {
		//		Oos = true;
		//	}
		//	else {
		//		Oos = false;
		//	}
		//}
		if (Oos == true) {
			lead = true;
			Debug.Log(transform.name + ": Out of my sight...");
		}
		else {
			var rotation = Quaternion.LookRotation(pos.position - transform.position);
			rotation.x = 0.0;
			rotation.z = 0.0;
			transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotDamp);
			var posRel = Vector3(pos.position.x,transform.position.y,pos.position.z);
			if (Vector3.Distance(transform.position, posRel) > precision) {
				animation["runSlow"].wrapMode = WrapMode.Loop;
				animation.CrossFade("runSlow", 0.2);
				rigidbody.velocity = (transform.forward * actSp)+(transform.right * actStr * strafe)+(transform.up*rigidbody.velocity.y);
			}
			else {
				animation.CrossFade("idle", 0.2);
			}
			Debug.Log(transform.name + ": Now following " + pos.name + " of " + leader.transform.name);
		}
	}
}

function FindLeader () {
	Debug.Log(transform.name + ": Hey I'm so fuckin' alone, guys!");
	if (leader == GetComponent(Squad1)) {
		var ldrs = FindObjectsOfType(Squad1);
		for (var i : int; i<leaders.length; i++) {
			leaders[i] = ldrs[i];
		}
		for (var ldr : Squad1 in leaders) {
			if (ldr != GetComponent(Squad1)  ldr.lead == true  ldr.fullSquad == false  Vector3.Distance(transform.position,ldr.transform.position) < maxLdrDist) {
				leader = ldr;
			}
		}
	}
}

To test it, just attach it to some character model (I took the soldier from a tutorial), than create some emptys and make them childs of the character, copy the character several times and set one of them to be group leader (just enable “lead”)…

okay, problem solved…

So what was the problem you experienced?

could you possible post the finished script this would be great for an fps

okay, here’s a first version of the code, it’s features are:
-squad movement
-finding cover
-attacking
-following waypoints
-etc…

These parts aren’t working correctly:
-finding cover(
(the characters simply stay stuck in the walls sometimes…)
-following waypoints
(I don’t know why this isn’t working)

Squad1.js

var speed = 3.6;
var runSp = 2.0;
var strafe = 2.0;
private var actStr = 0.0;
// actSp = actual speed...
var actSp = 3.6;
var rotDamp = 6.0;
var rotMod = 6.0;
var hitPoints = 100.0;
var armor = 35.0;
var minDmg = 0.1;
var deadReplacement : Transform;

// Everything for squad movement...
var precision = 0.4;
// atkPrec = precision when attacked...
var atkPrec = 3.0;
var lead : boolean = false;
private var leadingNow : boolean = false;
private var takeLead : boolean = false;
private var leadSwitch = Random.Range(1.5,3.5);
private var ldrLostT = 1.0;
var leader : Squad1;
var leaders : Squad1[];
var maxLdrDist = 25.0;
var followPos : Transform[];
var followBool : Transform[];
var fullSquad : boolean = false;
private var num : int = 0;
var pos : Transform;
// Oos = Out Of Sight...
var Oos : boolean = false;
// atkd = attacked...
var atkd : boolean = false;
var cover : Transform;
var cvrPos : Vector3;
var covered : boolean = false;
var cvrLayer : LayerMask;
var cvrDist = 3.0;
var maxCvrDist = 7.0;
// wayPts = waypoints...
var wayPts : Transform[];
var wayPtTag : String;
var onWay : boolean = false;
var ptObj : Transform;
var curPt : int = 0;

// Attacking and enemy interaction...
var target : Transform;
var targetTag : String;
var attacking : boolean = false;
var strafeFire : boolean = false;
var combatLayers : LayerMask;
var atkRange = 25.0;
var fireRange = 15.0;
var eDist = 0.0;
var upperBody : Transform;
var curWeapon : Transform;

// Some animation options...
var anim : Animation;
var useFireAnim : boolean = true;
var normLookDir : Transform;

// Some speaking...
var hitSound : AudioClip[];
var dieSound : AudioClip[];
var cvrSound : AudioClip;
var fireOrder : AudioClip;
var followOrder : AudioClip;
var leaderLost : AudioClip;
private var lastS = 1.0;

// Some variables for the npc's character...
private var assurance = 1.3;
private var power = 2.0;
private var courage = 1.3;
private var defensive = 0.9;
private var curEmo = 1.0;

function Start () {
	if (GetComponent(PersonalityGenerator1)) {
		var persona = GetComponent(PersonalityGenerator1);
		assurance = persona.assurance;
		power = persona.power;
		courage = persona.courage;
		defensive = persona.defensive;
		curEmo = persona.emo;
	}
	ClosestLeader();
	ClosestEnemy();
	ClosestWayPt();
	if (anim == null) {
		anim = GetComponent(Animation);
	}
	if (anim.animation["shoot0"]) {
		anim.animation.AddClip(animation["shoot0"].clip, "shootUpperBody");
		anim.animation["shootUpperBody"].AddMixingTransform(upperBody);
		anim.animation["strafeL"].layer = -1;
		anim.animation["coverWalk"].wrapMode = WrapMode.Loop;
	}
}
	
function FixedUpdate () {
	if (lead == false  leader == null) {
		ClosestLeader();
		if (leadingNow == true) {
			lead = true;
		}
	}
//		var ldrs = FindObjectsOfType(Squad1);
//		for (var i : int; i<leaders.length; i++) {
//			if (ldrs[i] != null  ldrs[i].lead == true) {
//				leaders[i] = ldrs[i];
//			}
//		}
//		for (var ldr : Squad1 in leaders) {
//			if (ldr != null  ldr != GetComponent(Squad1)  ldr.lead == true  ldr.fullSquad == false  Vector3.Distance(transform.position,ldr.transform.position) < maxLdrDist) {
//				leader = ldr;
//			}
//		}
//		FindLeader();
//		if (Time.time > lastS + leaderLost.length*2) {
//			audio.PlayOneShot(leaderLost);
//		}
//	}
	if (lead == true) {
		//check if our squad arrived at its maximum size
		for (var posi : Transform in followBool) {
			if (posi != null) {
				fullSquad = true;
			}
			else {
				fullSquad = false;
			}
		}
	}
	if (lead == false  leader != null  pos == null) {
		// Search for a free follow point if the squad isn't full yet
		if (num < leader.followPos.length  leader.fullSquad == false) {
			if (leader.followBool[num] == null) {
				Debug.Log(transform.name + ": Squadleader found!");
				pos = leader.followPos[num];
				leader.followBool[num] = leader.followPos[num];
				num = 0;
			}
			if (leader.followBool[num] != null) {
				Debug.Log(transform.name + ": Still searching...");
				num += 1;
			}
			ClosestLeader();
		}
		else {
			//Check for a new leader
			leader = null;
			ClosestLeader();
			pos = null;
			num = 0;
		}
	}
	//var hit : RaycastHit;
	//if (Physics.Linecast(transform.position, pos.position, hit)) {
	//	if (hit.transform != null) {
	//		Oos = true;
	//	}
	//	else {
	//		Oos = false;
	//	}
	//}
	if (Oos == true) {
		lead = true;
		Debug.Log(transform.name + ": Out of my sight...");
	}
	//Rotation variables...
	var rotation : Quaternion;
	transform.rotation.x = 0.0;
	transform.rotation.z = 0.0;

	//check for next enemy
	if (target == null) {
		ClosestEnemy();
		attacking = false;
	}
	else {
		//check if we can see straight onto the target
		var ehit : RaycastHit;
		if (Physics.Linecast(transform.position,target.position,ehit,combatLayers)) {
			if (ehit.transform == target || ehit.transform.parent == target) {
				//if enemy is in range, switch to attack mode...
				if (ehit.distance < atkRange) {
					attacking = true;
					atkd = true;
				}
				else {
					atkd = true;
				}
			}
			//if not, cancel attack mode...
			else {
				attacking = false;
			}
		}
	}
	// If we are attacking the enemy:
	if (attacking == true) {
		//Check the distance between us and the enemy
		eDist = Vector3.Distance(transform.position,target.position);
		//Rotate towards it:
		if (target != null) {
			rotation = Quaternion.LookRotation(target.position - transform.position);
		}
		//Or towards the follow point if enemy is null...
		else {
			rotation = Quaternion.LookRotation(pos.position - transform.position);
		}
		//Then do the rotation:
		transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotDamp);

		// if the enemy comes into attacking range...
		if (eDist < atkRange  eDist > fireRange) {
			//... start aiming at him, ...
			if (anim.GetComponent("HeadLookController")) {
				anim.GetComponent("HeadLookController").target = target.position;
			}
			//... give a fire order, ...
			if (Time.time > lastS + Random.Range(fireOrder.length*3,10.0)) {
				audio.PlayOneShot(fireOrder);
				lastS = Time.time;
			}
			//... and go closer to the enemy to shoot him.
			if (eDist > fireRange+0.1) {
				anim.animation["coverWalk"].wrapMode = WrapMode.Loop;
				anim.animation.CrossFade("coverWalk", 0.05);
				rigidbody.velocity = (transform.forward * actSp/runSp*1.7)+(transform.right * actStr * strafe)+(transform.up*rigidbody.velocity.y);
			}
			else {
				rigidbody.velocity = (transform.forward * actSp/runSp*1.7)+(transform.up*rigidbody.velocity.y)+(transform.right*rigidbody.velocity.x);
			}
		}
		// If enemy is closer than firing range, ...
		if (eDist < fireRange) {
			// ... keep aiming on him, ...
			if (anim.GetComponent("HeadLookController")) {
				anim.GetComponent("HeadLookController")	.target = target.position;
			}
			// ... and open fire!
			if (curWeapon) {
				curWeapon.SendMessage("Fire", SendMessageOptions.DontRequireReceiver);
			}
			// If enabled, walk around the target and keep shooting ...
			if (strafeFire == true) {
				rigidbody.velocity = (transform.forward * actSp/rotMod)+(transform.right * -1 * strafe)+(transform.up*rigidbody.velocity.y);
				anim.animation["strafeL"].wrapMode = WrapMode.Loop;
				anim.animation.CrossFade("strafeL", 0.2);
				if (useFireAnim == true) {
					animation.CrossFadeQueued("shootUpperBody", 0.3, QueueMode.PlayNow);
				}
			}
			// ... or just stand there and blow him to hell!
			else {
				if (useFireAnim == true) {
					// Play a fire animation:
					anim.animation["shoot1"].wrapMode = WrapMode.Loop;
					anim.animation.CrossFade("shoot1", 0.2);
				}
				else {
					// Play animation depending on if we are standing or shooting from cover.
					if (covered == true) {
						anim.animation.CrossFade("coverIdle", 0.05);
					}
					else {
						anim.animation.CrossFade("idle", 0.05);
					}
				}
			}
		}
	}
	// If we aren't attacking the target:
	else {
		// Aim straight in front of you:
		if (anim.GetComponent("HeadLookController")) {
			anim.GetComponent("HeadLookController").target = normLookDir.position;
		}
		if (covered == false) {
			if (leader != null  pos != null) {
				// rotate towards the point we are following:
				rotation = Quaternion.LookRotation(pos.position - transform.position);
				rotation.x = 0.0;
				rotation.z = 0.0;
				transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotDamp);
			}
			else {
				// or look for a new leader if we lost the old one:
				ClosestLeader();
			}
		}
		// if we are attacked and currently covered, but when we ca't see an enemy:
		if (atkd == true  covered == true) {
			// rotate towards a cover or place to hide behind:
			if (cover != null) {
				rotation = Quaternion.LookRotation(cvrPos - transform.position);
				rotation.x = 0.0;
				rotation.z = 0.0;
				transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotDamp * defensive);
			}
			// If there's no such place, ...
			else {
				// ... keep following the squad leader.
				rotation = Quaternion.LookRotation(pos.position - transform.position);
				rotation.x = 0.0;
				rotation.z = 0.0;
				transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotDamp);
			}
		}
		// If we are not the squad leader:
		if (pos != null  lead == false) {
			// Find the follow point's position:
			var posRel = Vector3(pos.position.x,transform.position.y,pos.position.z);
			// If we are not being attacked:
			if (atkd == false) {
				// If the point is to far away:
				if (Vector3.Distance(transform.position, posRel) > precision) {
					// ... play a movement animation, ...
					if (anim.animation["runSlow"]) {
						anim.animation["runSlow"].wrapMode = WrapMode.Loop;
						anim.animation.CrossFade("runSlow", 0.1);
					}
					else {
						anim.animation.CrossFade("coverWalk", 0.15);
					}
					// ... and simply move, until we are close enough.
					rigidbody.velocity = (transform.forward * actSp)+(transform.right * actStr * strafe)+(transform.up*rigidbody.velocity.y);
				}
				// If we are close enough, ...
				else {
					// ... let's just stand around.
					anim.animation.CrossFade("idle", 0.2);
				}
				// ... and tell the user who we are following:
				Debug.Log(transform.name + ": Now following " + pos.name + " of " + leader.transform.name);
			}
			// But if we are being attaked:
			else {
				// and if we are covered, ...
				if (covered == true) {
					// ... If the distance to our leader is longer than it should, ...
					if (Vector3.Distance(transform.position, leader.transform.position) > atkPrec * assurance * courage) {
						if (Vector3.Distance(transform.position, cvrPos) > cvrDist*10) {
							// ... then just come closer to the leader.
							if (anim.animation["coverWalk"]) {
								anim.animation["coverWalk"].wrapMode = WrapMode.Loop;
								anim.animation.CrossFade("coverWalk", 0.1);
							}
							else {
								anim.animation["walk"].wrapMode = WrapMode.Loop;
								anim.animation.CrossFade("walk", 0.1);
							}
							rigidbody.velocity = (transform.forward * actSp/runSp*1.7)+(transform.right * actStr * strafe)+(transform.up*rigidbody.velocity.y);
						}
						else {
							// or just keep sitting around.
							if (anim.animation["coverIdle"]) {
								anim.animation.CrossFade("coverIdle", 0.2);
							}
							else {
								anim.animation.CrossFade("idle", 0.2);
							}
						}
					}
					// But if the distance to the leader is short:
					else {
						// ... just stand around.
						covered = false;
						cover = null;
						anim.animation.CrossFade("idle",0.3);
					}
					// But now let's search for possible covers:
					var cvrs = GameObject.FindGameObjectsWithTag("cover");
					for (var cvr : GameObject in cvrs) {
						var cvF : RaycastHit;
						if (Physics.Linecast(transform.position, cvr.transform.position, cvF, cvrLayer)) {
							// ... and select a very close one.
							if (cvF.distance < (maxCvrDist*defensive*assurance/courage)) {
								cover = cvF.transform;
								cvrPos = cvF.point;
							}
						}
					}
				}
				// If we are not hiding but still being attacked:
				else {
					//... and if we are far away from follow point:
					if (Vector3.Distance(transform.position, posRel) > atkPrec) {
						//... simply run towards it.
						if (anim.animation["runFast"]) {
							anim.animation["runFast"].wrapMode = WrapMode.Loop;
							anim.animation.CrossFade("runFast", 0.2);
						}
						else {
							anim.animation["coverWalk"].wrapMode = WrapMode.Loop;
							anim.animation.CrossFade("coverWalk", 0.2);
						}
						rigidbody.velocity = (transform.forward * actSp * runSp)+(transform.right * actStr * strafe)+(transform.up*rigidbody.velocity.y);
					}
					// otherwise just stand around like a stupid...
					else {
						anim.animation.CrossFade("idle", 0.2);
					}
				}
			}
		}
	}
	// If we are the squad leader:
	if (lead == true) {
		// and if we aren't being attacked or attacking and if we've got waypoints:
		if (atkd == false  attacking == false  ptObj != null) {
			// Aim straight in front of us:
			if (anim.GetComponent("HeadLookController")) {
				anim.GetComponent("HeadLookController").target = normLookDir.position;
			}
			// And follow the current waypoint...
			onWay = true;
			rotation = Quaternion.LookRotation(ptObj.position - transform.position);
			rotation.x = 0.0;
			rotation.z = 0.0;
			transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * 3);
			var wayPt = ptObj.GetComponent(SquadWayPoint1);
			// ... as long as it is at a certain distance:
			if (Vector3.Distance(transform.position,ptObj.position) >= precision) {
				ImThere = false;
				rigidbody.velocity = (transform.forward * actSp)+(transform.up*rigidbody.velocity.y);
				anim.animation["coverWalk"].wrapMode = WrapMode.Loop;
				anim.animation.CrossFade("coverWalk", 0.05);
			}
			// otherwise just take the next one or wait:
			else {
				animation.CrossFade("idle", 0.2);
				if (wayPt.holdPos == true) {
					if (ImThere == false) {
						holdT = Time.time;
						ImThere = true;
					}
					if (Time.time > holdT + wayPt.holdT) {
						nextPt = Random.Range(0,wayPt.wayPts.length+1);
						if (nextPt < wayPt.wayPts.length) {
							ptObj = wayPt.wayPts[nextPt];
						}
						else {
							ptObj = wayPt.wayPts[wayPt.priority];
						}
					}
				}
				else {
					ptObj = ptObj.GetComponent(SquadWayPoint1).wayPts[ptObj.GetComponent(SquadWayPoint1).priority];
				}
			}
		}
		// But if we don't have any waypoint:
		if (atkd == false  attacking == false  ptObj == null) {
			// we are not on a way, so...
			onWay = false;
			// ... let's just stand 'round.
			rigidbody.velocity = (Vector3.zero)+(transform.up*rigidbody.velocity.y);
		}
	}
}

function FindLeader () {
	Debug.Log(transform.name + ": Hey, I'm so fuckin' alone, guys!");
	if (leader == GetComponent(Squad1)) {
		var ldrs = FindObjectsOfType(Squad1);
		for (var i : int; i<leaders.length; i++) {
			leaders[i] = ldrs[i];
		}
		for (var ldr : Squad1 in leaders) {
			if (ldr != GetComponent(Squad1)  ldr.lead == true  ldr.fullSquad == false  Vector3.Distance(transform.position,ldr.transform.position) < maxLdrDist) {
				leader = ldr;
			}
		}
	}
}

function ClosestLeader () { //: GameObject
	if (lead == false  leader == null) {
		// Find all game objects with our tag
		var gos : GameObject[];
		gos = GameObject.FindGameObjectsWithTag(gameObject.tag);
		var closest : GameObject;
		var distance = Mathf.Infinity;
		var position = transform.position;
		// Iterate through them and find the closest one
		for (var go : GameObject in gos) {
			if (go.GetComponent(Squad1)  go.GetComponent(Squad1).lead == true  go.GetComponent(Squad1).fullSquad == false) {
				var diff = (go.transform.position - position);
				var curDistance = diff.sqrMagnitude;
				if (curDistance < distance) {
					closest = go;
					distance = curDistance;
					leader = go.GetComponent(Squad1);
				}
			}
		}
		//return closest;
	}
	if (leader == null) {
		if (leadingNow == false  takeLead == false) {
			ldrLostT = Time.time;
			takeLead = true;
		}
		if (leadingNow == false  takeLead == true  Time.time > ldrLostT + leadSwitch) {
			leadingNow = true;
			if (anim.animation["wink"]) {
				anim.animation.CrossFade("wink", 0.2);
			}
		}
		if (leadingNow == true) {
			leader = null;
			lead = true;
			if (Time.time > lastS + Random.Range(7.0,27.0)) {
				if (attacking == false) {
					audio.PlayOneShot(followOrder, assurance);
				}
				else {
					audio.PlayOneShot(fireOrder, assurance);
				}
				lastS = Time.time;
			}
		}
	}
	yield new WaitForSeconds(0.5); 
}

function ClosestEnemy () { //: GameObject
	// Find all game objects with enemy's tag
	var gos : GameObject[];
	gos = GameObject.FindGameObjectsWithTag(targetTag);
	var closest : GameObject;
	var distance = Mathf.Infinity;
	var position = transform.position;
	// Iterate through them and find the closest one
	for (var go : GameObject in gos) {
		var diff = (go.transform.position - position);
		var curDistance = diff.sqrMagnitude;
		if (curDistance < distance) {
			closest = go;
			distance = curDistance;
			target = go.transform;
		}
	}
	//return closest;
	yield new WaitForSeconds(1);
}

function ClosestWayPt () { //: GameObject
	// Find all waypoint gameObjects
	var gos : GameObject[];
	gos = GameObject.FindGameObjectsWithTag(wayPtTag);
	var closest : GameObject;
	var distance = Mathf.Infinity;
	var position = transform.position;
	// Iterate through them and find the closest one
	for (var go : GameObject in gos) {
		var diff = (go.transform.position - position);
		var curDistance = diff.sqrMagnitude;
		if (curDistance < distance) {
			closest = go;
			distance = curDistance;
			ptObj = go.transform;
			//wayPts = go.GetComponent(SquadWayPoint1).wayPts;
			//for (var i : int; i<wayPts.length; i++) {
			//	if (wayPts[i] == go.transform) {
			//		curPt = i;
			//	}
			//}
		}
	}
	//return closest;
	yield;
}

function ApplyDamage (dmg : float) {
	if (dmg >= minDmg) {
		if (armor > 0.0) {
			if (armor < dmg) {
				armor -= dmg;
				hitPoints -= (dmg - armor)/1.5;
			}
			else {
				armor -= dmg;
			}
		}
		else {
			hitPoints -= dmg;
			if (hitPoints <= 0.0) {
				Detonate();
			}
		}
		atkd = true;
		if (Time.time > lastS + cvrSound.length*4) {
			var goCvrd = (Random.Range(0.0,10)*courage)-defensive*2;
			if (goCvrd < 5.0) {
				cvrd = true;
				audio.PlayOneShot(cvrSound);
			}
			else {
				cvrd = false;
				audio.PlayOneShot(hitSound[Random.Range(0,hitSound.length)]);
			}
			lastS = Time.time;
		}
	}
}

function Detonate () {
	Destroy(gameObject);	
	if (dieSound)
		AudioSource.PlayClipAtPoint(dieSound[Random.Range(0,dieSound.length)], transform.position);

	// Replace ourselves with the dead body
	if (deadReplacement) {
		var dead : Transform = Instantiate(deadReplacement, transform.position, transform.rotation);
		
		// Copy position  rotation from the old hierarchy into the dead replacement
		CopyTransformsRecurse(transform, dead);
	}
}

static function CopyTransformsRecurse (src : Transform,  dst : Transform) {
	dst.position = src.position;
	dst.rotation = src.rotation;
	
	for (var child : Transform in dst)
	{
		// Match the transform with the same name
		var curSrc = src.Find(child.name);
		if (curSrc)
			CopyTransformsRecurse(curSrc, child);
	}
}

And the waypoint script:

// The possible directions characters can go:
var wayPts : Transform[];
// The waypoint they should prefer:
// (indicated by wayPts' index numbers)
var priority : int = 1;
// should characters protect this position or wait there?
var holdPos : boolean = false;
// how long should they wait there for enemies?
var holdT = 10.0;

It’s veeerrrryyyy long, but at least, my enemies are less stupid than the ones fom fps-tutorial, also, using the headLookController.cs script, they can aim correctly at their current target…

hey, if you want an intelligent pathfinding system, i suggest asking surestone, he developed a A* pathfinding system as well as one that will work for the fps controller.

when i tried putting this in my game, i got multiple errors, including SquadWaypoint1 and PersonalityGenerator1 were unkown identifiers, can you help

Oh, the AI script must be called squad1.js , the waypoint script’s name is squadWaypoint1.js … You can delete the “personality generator” part in the Start() function, that was only some idea, but it’s not working like it should, so just ignore it…

Then you need the headLookController.cs from:
http://unity3d.com/support/resources/unity-extensions/head-look-controller
It must be attached to the “anim” called object; this one is the child/object which has the Animation component attached to it.

Also, you can change the animations’ names inside the code so that they fit with your characters.

PS: If anyone kows how to fix that waypoint problem, any help is welcome… The problem is that the squad leader follows the waypoints until he comes to the nearest one, than simply stops, but still reacts on the player or any other target in coming into its range.