- Home /
NavmeshAgent Behavior
Hi all,
I am attaching my current script;
// Use this for initialization
void Start () {
agent = GetComponent<NavMeshAgent> ();
timer = wanderTimer;
target = GameObject.FindGameObjectWithTag ("Player").transform;
Water = GameObject.FindGameObjectWithTag ("Water").transform;
myAudio = GetComponent<AudioSource> ();
anim = GetComponent<Animator> ();
lifecheck = target.GetComponent<Life> ().life;
}
// Update is called once per frame
void Update () {
timer += Time.deltaTime;
targetPos = target.position;
AIpos = transform.position;
Vector3 direction = targetPos - AIpos;
float angle = Vector3.Angle (direction, transform.forward);
if (angle < 180 * 0.5f) {
RaycastHit hit;
if(Physics.Raycast(transform.position + transform.up, direction.normalized, out hit, 40f))
{
if (hit.collider.tag == "Player") {
playerInSight = true;
lastRegisteredPlayerPos = targetPos;
Searching = false;
SearchNewPath = false;
agent.stoppingDistance = 17f;
}
else
{
playerInSight = false;
agent.stoppingDistance = 3f;
agent.SetDestination (lastRegisteredPlayerPos);
goingToLastSpot = true;
SearchNewPath = false;
}
}
}
if (transform.position != delayedPos) {
anim.SetFloat ("Move", 0.2f);
SearchNewPath = false;
} else {
anim.SetFloat ("Move", 0f);
}
if (goingToLastSpot) {
if (agent.remainingDistance <= agent.stoppingDistance) {
Searching = true;
SearchNewPath = true;
goingToLastSpot = false;
}
}
if (playerInSight) {
transform.LookAt (targetPos);
agent.Resume();
agent.ResetPath();
if (Vector3.Distance (AIpos, targetPos) <= 17f && lifecheck > 0f) {
if (!inCooldown) {
inCooldown = true;
anim.SetTrigger ("Spell");
}
}
else {
agent.SetDestination (targetPos);
}
}
if (!agent.pathPending && !goingToLastSpot)
{
if (agent.remainingDistance <= agent.stoppingDistance)
{
if (!agent.hasPath || agent.velocity.sqrMagnitude == 0f)
{
SearchNewPath = true;
}
}
}
if (timer >= wanderTimer && Searching && SearchNewPath) {
Vector3 newPos = RandomNavSphere(transform.position, wanderRadius, -1);
transform.LookAt (newPos);
CurrentPath = newPos;
SearchNewPath = false;
agent.Resume();
agent.SetDestination(newPos);
timer = 0;
}
if (inCooldown) {
Cooldown -= Time.deltaTime;
if (Cooldown <= 0) {
Cooldown = Random.Range (0.5f, 0.6f);
inCooldown = false;
}
}
}
void LateUpdate() {
delayedPos = transform.position;
}
public static Vector3 RandomNavSphere(Vector3 origin, float dist, int layermask) {
Vector3 randDirection = Random.insideUnitSphere * dist;
randDirection += origin;
NavMeshHit navHit;
NavMesh.SamplePosition (randDirection, out navHit, dist, 1 << NavMesh.GetAreaFromName ("Walkable"));
return navHit.position;
}
This is supposed to move the agent randomly (wander) until he sees the player. If the player's too far, he attempts to go near him. If the player is within "attacking distance", he will fire a projectile. If the player suddenly goes out of sight, the AI will attempt to go the last location the player was seen and once it reaches the destination, the searching restarts.
My problem is that the AI currently is very unrealistic. For some reason he keeps going to extremely random locations, staring at obstacles (which is not the ideal case if I want to instill a "wander"-type of behavior) and sometimes keeps playing the walking animation, even if he stands idle; thus, for some reason the script thinks that he is moving. The random locations makes perfect sense, since I am using Random.UnitSphere(), but I was wondering if I could use a while loop in order to find more "probable" areas that the player can be at. He usually wanders within specific areas that are obstructed by mountains and he stands there watching them, although the waiting time has been set to only 1.5 seconds. The player is thus very unlikely to appear to those areas and it is quite frustrating.
What do you think I should change to make it more realistic? There is a map of walkable areas and unwalkable (specifically restricted to the AI only) and I would like him to explore the entire area in search of the player. I would honestly want to avoid the typical WayPoints system, if possible.
Thank you for your attention!