- Home /
raycast hit not detecting && Nav mesh agent ai stealth
Hello, I'm trying to make patrol ai that detects a player within its field of view then moves to that players last known position and looses track of player once the player is out of sight. The script I have works fine in pathfinding the waypoints I set when it is searching for the player, but completely ignores the player. The sphere collider is marked trigger and proper public variables are set in the inspector, please help.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class StealthAI : MonoBehaviour {
public float fieldOfViewAngle = 110f; // Number of degrees, centred on forward, for the enemy see.
public bool playerInSight = false; // Whether or not the player is currently sighted.
public Vector3 personalLastSighting; // Last place this enemy spotted the player.
public GameObject player; //Player Target
public string tagofcollider = "Player";
public Light lt; //Search Light Attatched to Object
public float dirchangefrequency = Random.Range(3,14); //How often the Ai finds new waypoint when wandering
public Transform waypt1; //Waypoint 1
public Transform waypt2; //Waypoint 2
public Transform waypt3; //Waypoint 3
public Transform waypt4; //Waypoint 4
private NavMeshAgent agent; // Reference to the NavMeshAgent component.
private SphereCollider col; // Reference to the sphere collider trigger component
private float StoppingDistance = 3.5f; //How close till faliure state
private float timetillchange = 0; //timer affected by time.deltatime DO NOT CHANGE VALUE FROM 0
private bool changingdir = false; //Is changedir being called?
private Transform Waypoint; //Current wandering waypoint being set
private float cooldowntime;
void Start () {
player = GameObject.FindWithTag ("Player");
agent = GetComponent<NavMeshAgent> ();
lt = GetComponent<Light> ();
playerInSight = false;
cooldowntime = dirchangefrequency;
}
void OnTriggerStay (Collider other){
// If the player has entered the trigger sphere...
if(other.gameObject.tag == tagofcollider){
// By default the player is not in sight.
playerInSight = false;
// Create a vector from the enemy to the player and store the angle between it and forward.
Vector3 direction = other.transform.position - transform.position;
float angle = Vector3.Angle(direction, transform.forward);
// If the angle between forward and where the player is, is less than half the angle of view...
if(angle < fieldOfViewAngle * 0.5f){
RaycastHit hit;
// ... and if a raycast towards the player hits something...
if(Physics.Raycast(transform.position - transform.up, direction.normalized, out hit, col.radius)){
// ... and if the raycast hits the player...
if(hit.collider.gameObject.tag == tagofcollider){
// ... the player is in sight.
playerInSight = true;
agent.speed = 8;
// Set the last global sighting is the players current position.
personalLastSighting = player.transform.position;
}
}
}
}
}
void OnTriggerExit (Collider other){
// If the player leaves the trigger zone...
if(other.gameObject.tag == tagofcollider)
// ... the player is not in sight.
playerInSight = false;
}
void Update (){
Vector3 forward = transform.TransformDirection(Vector3.forward) * 45;
Debug.DrawRay(transform.position-transform.up, forward, Color.green);
//check if changin Dir at the moment, if not add to timer
if(!changingdir && playerInSight == false){
timetillchange += Time.deltaTime;
}
//when timer reaches # seconds, call Dir Change function
if(timetillchange >= dirchangefrequency){
StartCoroutine(ChangeDir());
}
float dist = Vector3.Distance(player.transform.position, transform.position);
if (playerInSight = true) {
agent.SetDestination (personalLastSighting);
}
else if (dist < StoppingDistance) {
agent.Stop();
lt.intensity += 2;
GetComponent<AudioSource> ().Play ();
Invoke("Restart",1);
}
else if (dist > StoppingDistance)
lt.intensity = 1;
}
void Restart (){
Application.LoadLevel (Application.loadedLevel);
}
IEnumerator ChangeDir(){
changingdir = true;
timetillchange = 0;
int randomPick = Random.Range(0,5);
if(randomPick == 1)
Waypoint = waypt1;
else if(randomPick == 2)
Waypoint = waypt2;
else if(randomPick == 3)
Waypoint = waypt3;
else if(randomPick == 4)
Waypoint = waypt4;
yield return new WaitForSeconds (cooldowntime);
agent.speed = 3;
agent.SetDestination (Waypoint.position);
changingdir = false;
}
}
Answer by redeemer · May 18, 2015 at 05:21 AM
Hi,
We've just released this fov plugin you might be interested in. It comes with various examples, one of those is an AI that follows the player when detected and returs to the start position when the player is no longer detected. Another example is a security camera that focus on the player as long it's detected and return to the normal scaning mode when the player is not detected.
https://www.assetstore.unity3d.com/en/#!/content/30415
I can leave here the script being use in the example scene so you see how easy it is with it.
using FoV2;
using UnityEngine;
using System.Collections;
namespace FoVDemo {
public class Enemy : MonoBehaviour {
FoV fov;
Transform player;
bool playerDetected;
NavMeshAgent navAgent;
public Color fovDefaultColor;
public Color fovPlayerDetectedColor;
Vector3 initPos;
Vector3 targetPos;
// Use this for initialization
void Start () {
fov = GetComponentInChildren<FoV>();
player = GameObject.FindGameObjectWithTag("Player").transform;
playerDetected = false;
navAgent = GetComponent<NavMeshAgent>();
initPos = transform.position;
InvokeRepeating ("UpdateFoV", 0, 0.1f);
}
// Update is called once per frame
void UpdateFoV () {
DetectPlayer();
UpdateFoVColor();
if(playerDetected) {
navAgent.SetDestination(targetPos);
} else if(navAgent.remainingDistance <= 1) {
navAgent.SetDestination(initPos);
}
}
void DetectPlayer() {
if(fov.GetDetectedObjects().Contains(player)) {
playerDetected = true;
targetPos = player.position;
} else {
playerDetected = false;
}
}
void UpdateFoVColor() {
if(playerDetected) fov.GetComponent<Renderer>().material.color = fovPlayerDetectedColor;
else fov.GetComponent<Renderer>().material.color = fovDefaultColor;
}
}
}
As lovely as that would be to use I really just want to know why my code doesn't fully work, and due to the fact that my development budget is $0 I cannot buy your plugin yet.
You could put a Debug.Log(other.tag) as the first line in your OnTriggerStay method to be sure it triggers when the player enters the sphere collider (or implement OnTriggerEnter).
If it's not triggering the method at all you probably are lacking some "collision" requirements, like having a rigidbody on one of the two colliding objects. Quoted from http://docs.unity3d.com/ScriptReference/$$anonymous$$onoBehaviour.OnTriggerEnter.html
"Trigger events are only sent if one of the colliders also has a rigidbody attached."
If it's none of this, then you should provide more info about your scene and objects, because your code in those methods seems to be ok.
The player is the standard fps controller in unity5 with a is kinematic rigidbody attatched, and the enemy is just a light with a lens flare and sphere collider with the script attached.
Ok, some things that I see there could be a problem with :
The enemy has a sphere collider, but is it marked as Trigger?
For the OnTrigger... or OnCollision... events to be fired, one of the two objects colliding must have a NON kinematic rigidbody. So if your enemy does not have a non kinematic rigidbody and the rigidbody in your player is kinematic it won't work either.
If you want to raycast in front of the enemy use transform.forward ins$$anonymous$$d of transform.position-transform.up and use Space.Self
To detect the player, the player also has to have a collider attached and I don't know if it recognices the standard fps controller as the collider or you need to put one of your own, but if that's the case I think it would mess up with the fps controller, but not sure about this one.
Hope one of this makes the trick ;)
Your answer
Follow this Question
Related Questions
Enemy AI, detect player when seen 2 Answers
enemy raycast to detect player 1 Answer
180 Degree raycast 1 Answer
Physics.Raycast does not work On NotWalkable Areas Of Navmesh. 1 Answer
AI detection script problem 0 Answers