- Home /
navmesh ai check if ai is looking at you
Hi i have read through this question
http://answers.unity3d.com/questions/677004/navmesh-ai-follow-only-if-seen.html
and i still dont fully understand how to make the ai only travel to you when it sees you here is my current code its a modifed version of bordr's ufps simple ai
using UnityEngine;
using System.Collections;
public class AI : MonoBehaviour {
// By BorDr
// 9/7/13
//---------------------------------------------------------------------------------------------
// Use this however you like. Just keep this notice attatched. It is very basic and meant
// for use with the UFPS system. Take your model, add in the animations using the variables,
// add a Nav Mesh Agent for navigation (It is free with Unity 4.2!) a collider for a hitbox,
// an Audio Source with your attack sound to play when your enemy is attacking, and set the Stopping
// Distance on the Navmesh to something less than the Range varible, so the enemy will stop and attack
// when it gets close. Make sure your Player is tagged "Player" or else the enemy will not see the player.
// This is not meant as a complete solution, just something for prototyping. Use UFPS damage handler for AI health.
//---------------------------------------------------------------------------------------------
private Transform PlayerT;
private GameObject Player;
private float Timer = 1.5f;
public int Range;
public float MaxTimer = 1.5f;
public int followRange;
public AudioClip HitNoise;
Animator animator;
// Use this for initialization
void Start () {
//Search for the player, then set the player's transform for navigation.
Player = GameObject.Find("Player[Saveable]");
PlayerT = Player.transform;
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update () {
//The timer system I use is simple. It counts up- when it is at maximum, the enemy can attack.
//When it is not, it recharges in seconds.
if (Timer <= MaxTimer){
Timer += Time.deltaTime;
}
//This is the navigation. The enemy will move toward the player while playing it's running
//animation. If it is in range, it will stop playing the animation.
var distance = Vector3.Distance(transform.position, PlayerT.transform.position);
if (distance < followRange)
{
GetComponent<NavMeshAgent>().destination = PlayerT.position;
animator.SetBool("walk", true);
}
else
{
animator.SetBool("walk", false);
GetComponent<NavMeshAgent>().destination = transform.position;
}
//When the player is in range, the enemy will attack.
if (distance < Range)
{
animator.SetBool("attack",true);
Attack ();
}
else
{
animator.SetBool("attack",false);
}
}
void Attack () {
//If the player is in range, the attack animation will play, the timer will reset, and
//damage will be dealt. The audio clip will be played to add an effect to the attack.
if (Timer >= MaxTimer){
Timer = 0;
PlayerT.GetComponent<vp_PlayerDamageHandler>().Damage(1.0f);
audio.PlayOneShot(HitNoise);
}
//animator.SetBool("attack", false);
}
}
Answer by wesleywh · Dec 16, 2014 at 07:54 PM
So the way that I make it so that they only attack you if they see you is to use a raycast. Also I make it so that if they enter a trigger it says that that AI Character is capable of seeing the player. If I don't add that trigger the AI will be able to see infinity, or until it hits something with its raycast. Using a raycast is great because it will shoot from the front of the player making it exremely easy to check if he sees the player.
Here is some code that I use in my AI character. All of the following code I put in a single script course you can do it however you want.
First Add a Sphere Collider(Check is Trigger) to your character, this acts as a distance check. The following code is for that sphere check.
function OnTriggerStay(other : Collider){//This is to see if the player is within a certain distance of the AI.
if(other.gameObject.tag == "Player"){//Only do this on ppl tagged "Player"
var direction : Vector3 = other.transform.position - this.transform.position;
var angle : float = Vector3.Angle(direction, transform.forward);//Draw the angle in front of the AI
if(angle < fieldOfViewAngle * 0.5f)//This is the angle that the AI can see
{
var hit : RaycastHit;
if(Physics.Raycast(transform.position + transform.up, direction.normalized, hit, col.radius))//Check if the AI can see the player
{
playerInSight = true; //AI Character sees the player
DoWaypoints = false; //don't walk waypoints anymore
}
}
}
}
function OnTriggerExit(other : Collider)
{
if(other.gameObject==FindClosestPlayer())//this is calling a function that tries to find the closest gameobject tagged "Player"
{
playerInSight = false;
lastPlayerSighting = FindClosestPlayer().transform.position; //this is used to have the AI move to this location to start looking for the lost player
}
}
The Reason I do it this way is because if I want to adjust how far my character can see I just adjust the sphere collider size instead of having to dive into my code.
Here is the code to find the closest player:
function FindClosestPlayer() : GameObject{
var gos : GameObject[];
gos = GameObject.FindGameObjectsWithTag("Player");//Person to find
//gos = GameObject.FindGameObjectsWithTag("Other");//example if you want to have the AI find someone other than just a player
var closest : GameObject;//you will return this as the person you find.
var distance = Math.Infinity;
var position = transform.position;
for(var go: GameObject in gos)//go through all players in map
{
var diff = (go.transform.position - position);
var curDistance = diff.sqrMagnitude;
if(curDistance < distance)//is this player closer than the last one?
{
closest = go;//this is the closest player
distance = curDistance;//set the closest distance
}
}
return closest;//this is the closest player
}
Now that it sees that closest player you can implement some more code to make that AI character move to that closest player that it sees. I have used some global variables here in this code that you would need to have access to but I am sure you can figure that one out.
Hope all of this makes sense. Good luck!
EDIT: Ooh! Just noticed that you were writing in C# sorry about that. If you know how to convert the code already then great! If not here are some instructions:
Converting the code here shouldn't be too difficult though. Just change "function OnTriggerStay and Exit" to "void OnTriggerStay" and Exit. The find closest player will not be void but move "GameObject" from the right to the left and remove the ":". It should look like "GameObject FindClosestPlayer()". Then remove all of the "var" and replace it for what it actually is like Vector3, float, etc. Lastly on the raycast make sure that you have "out hit" not just "hit".
thanks for this ill convert it into c sharp and re post it here
ok im really gonna need help with this
bool playerInSight;
float fieldOfViewAngle;
Transform lastPlayerSighting;
// void OnTriggerStay(Collider other){//This is to see if the player is within a certain distance of the AI.
// if(other.gameObject.tag == "Player"){//Only do this on ppl tagged "Player"
// Vector3 direction = other.transform.position - this.transform.position;
//
// float angle = Vector3.Angle(direction, transform.forward);//Draw the angle in front of the AI
//
// if(angle < fieldOfViewAngle * 0.5f)//This is the angle that the AI can see
// {
// RaycastHit hit ;
//
// if(Physics.Raycast(transform.position + transform.up, direction.normalized, out hit, col.radius))//Check if the AI can see the player
// {
// playerInSight = true; //AI Character sees the player
// //DoWaypoints = false; //don't walk waypoints anymore
// }
// }
// }
// }
// void OnTriggerExit(Collider other)
// {
// if(other.gameObject == FindClosestPlayer())//this is calling a function that tries to find the closest gameobject tagged "Player"
// {
// playerInSight = false;
// lastPlayerSighting = FindClosestPlayer().transform.position; //this is used to have the AI move to this location to start looking for the lost player
//
// }
// }
//
//
//
// void FindClosestPlayer(Transform lastPlayerSighting) {
// GameObject[] gos;
// gos = GameObject.FindGameObjectsWithTag("Player");//Person to find
// //gos = GameObject.FindGameObjectsWithTag("Other");//example if you want to have the AI find someone other than just a player
// GameObject closest;//you will return this as the person you find.
// var distance = $$anonymous$$athf.Infinity;
// var position = transform.position;
// foreach(Transform go in gos)//go through all players in map
// {
// var diff = (go.transform.position - position);
// var curDistance = diff.sqr$$anonymous$$agnitude;
// if(curDistance < distance)//is this player closer than the last one?
// {
// closest = go;//this is the closest player
// distance = curDistance;//set the closest distance
// }
// }
// return closest;//this is the closest player
// }
"bool playerInSight" should be "private bool playerInSight" "float fieldofView" should be "public float fieldOfView" -> can then edit this in the inspector "Transform lastPlayerSighting" could be changed to "public Vector3 lastPlayerSighting"
What other issues are you seeing?
Your answer
![](https://koobas.hobune.stream/wayback/20220613174206im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
pick random point on navmesh 4 Answers
What is wrong with this code? (Solved) 0 Answers
NavMesh Agent pause? 3 Answers