public class CitizenAI : MonoBehaviour {
public Transform _myTransform;
public Transform workLocation;
public Transform target;
public float idleTime;
public enum State{
Hungry,
LookingForWork,
Working,
BringingRessourcesToWork,
Hunting,
Idle,
Waiting,
//Many more states but you get the idea
};
private float speed;
private float idleTimer;
void Update()
{
//Run any movement code that hasn't ran this frame
MoveTorwards();
switch (state){
//There's a case for every possible State, only listing relevant one here
//When entering a state, a villager should not have a target
//Villager just picked up resources from a storage barn and is bringing them
//to his workplace.
case State.BringingRessourcesToWork:
if(!target) //If there is no destination, acquire one.
{
target = workLocation;
//Make a call to StartPath only once
seeker.StartPath(_myTransform.position, target.position, OnPathComplete);
currentStateString = "Bringing needed ressources to work.";
}//villager has a valid target, only check if within range
//Here I check to see if the unit is within range of his destination
//I could probably check if the waypoint is path.vectorPath[path.vectorPath.Length - 1]
if(SquareDistance (_myTransform.position, target.position) < 4.5f)
{
dropRessoucesAtWork(); //drop work related resources
target = null; //clear the destination reference
state = assesNeeds(); //get a new state
}//end if distance is short enough
break;
//Here is another case where I perdiodically need to refresh the path.
case State.HuntingAnimal:
if(!target){ //Same principle as above, acquire a target and call StartPath
target = workLocation.parent.GetComponent<HunterScript>().getNextTarget();
if(target){
seeker.StartPath (_myTransform.position, target.position, OnPathComplete);
idleTimer = 8.0f; //Here I set a timer at 8 seconds
currentStateString = "Hunting";
}
else{
state = assessNeeds();
return;
}
}
idleTimer -= Time.deltaTime; //Every frame deduct deltaTime from the timer
if(idleTimer <= 0){//Once the timer reaches 0 recall StartPath (the deer might have moved)
seeker.StartPath (_myTransform.position, target.position, OnPathComplete);
idleTimer = 8.0f;
}
//if we're within a certain distance of the deer, do stuff
if(SquareDistance (_myTransform.position, target.position) < 500){
path = null;
target.GetComponent<DeerAI>().MarkForDeath();
//The code below simply sets the AI not to do anything for 3 seconds and play an archery animation
idleTimer = 3.0f;
state = State.Waiting;
playArcheryAnim();
lastState = State.GoingForKill;
idleTimer = idleTime;
}
break;
}//end switch (state)
}//end update
private void MoveTorwards(){
if (path == null) {
return;
}
if (currentWaypoint >= path.vectorPath.Count) {
//End of path reached
path = null;
return;
}
if(!bentDown){
playWalkCycle();
}
_myTransform.position = Vector3.Slerp (_myTransform.position, path.vectorPath[currentWaypoint],
speed * Time.deltaTime);
//Check if we are close enough to the next waypoint
//If we are, proceed to follow the next waypoint
if (SquareDistance(_myTransform.position,path.vectorPath[currentWaypoint]) < 4) {
currentWaypoint++;
if (currentWaypoint < path.vectorPath.Count) {
Vector3 lookDirection = path.vectorPath[currentWaypoint];
lookDirection.y = this._myTransform.position.y;
transform.LookAt(lookDirection);
}
return;
}
}
private float SquareDistance(Vector3 a, Vector3 b){
Vector3 diff = b - a;
return diff.sqrMagnitude;
}
}