Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

OnTriggerStay/Enter

Discussion in 'Navigation' started by LionFische, Feb 11, 2016.

  1. LionFische

    LionFische

    Joined:
    Oct 16, 2015
    Posts:
    107
    Hi all, I'm having an issue with a detection script I am running.

    I have patrols moving around a sandbox, moving between nav points. I have added a cube to them with a detection script to act as a detection zone. When the player enters the detection zone, I fire a raycast from the patrol to the player.

    I use OnTriggerEnter/Stay/Exit.

    The strange thing is, the code works when the player enters and exits, I have a message to debug.log announcing the states, but the Stay does not seem to register.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PatrolDetection : MonoBehaviour {
    5.  
    6.     public RaycastHit hit;
    7.  
    8.     public bool isDetected = false;
    9.  
    10.     void OnTriggerEnter(Collider other)
    11.     {
    12.  
    13.         if (Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit))
    14.         {
    15.             if(hit.collider.gameObject.name == "Player")
    16.             {
    17.                 Debug.Log ("The " + other + " entered the collider");
    18.                 isDetected = true;
    19.                 Debug.Log ("I can see the " + other);              
    20.                 Debug.DrawLine (transform.parent.position, hit.point);
    21.             }
    22.         }
    23.     }
    24.  
    25.     void OnTriggerStay(Collider other)
    26.     {
    27.  
    28.         if (Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit))
    29.         {
    30.             if(hit.collider.gameObject.name == "Player")
    31.             {
    32.                 Debug.Log ("The " + other + " is staying in the collider");
    33.                 isDetected = true;
    34.                 Debug.Log ("I can see the " + other);              
    35.                 Debug.DrawLine (transform.parent.position, hit.point);
    36.             }
    37.         }
    38.     }
    39.  
    40.     void OnTriggerExit(Collider other)
    41.     {
    42.         isDetected = false;
    43.         if(other.gameObject.CompareTag("Player"))
    44.         {
    45.             Debug.Log("The " + other + " is no longer detected");
    46.         }
    47.     }
    48. }
    49.  
    I'm really not sure what could be going wrong. The code for Enter and Stay are the same and I imagine should both function the same.

    2h
     
  2. LionFische

    LionFische

    Joined:
    Oct 16, 2015
    Posts:
    107
    Well I seem to have resolved the issue. I don't understand why this has made a difference, but it has.

    I had a rigidbody on the patrol that the above script was attached to. I have now removed it and attached a rigidbody to the player instead. Now the OnTriggerStay method is functioning along with the other two functions and my patrol is continually detecting and raycasting to the player as I wanted. Confusing.

    The next issue is how to stop raycast going through other objects. I want my player to be able to hide behind a wall from a raycast. The idea being that he may be detected but not necessarily seen.

    Any thoughts appreciated.

    2h
     
  3. pixxelbob

    pixxelbob

    Joined:
    Aug 26, 2014
    Posts:
    111
    Probably something to do with your rigid body setup. Glad that's solved.
    You need to give your walls colliders so the raycast hit the walls.
     
  4. LionFische

    LionFische

    Joined:
    Oct 16, 2015
    Posts:
    107
    Hi PBob, thanks for getting back.

    I'm still having issues with this.

    I have colliders on the walls (not set as triggers), but yet the raycast goes right through them. I really don't know why. I've tried quite a few variations with no luck.

    Here is the code as it stands.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PatrolDetection : MonoBehaviour {
    5.  
    6.     public LayerMask sightBlockingLayers;
    7.  
    8.     public RaycastHit hit;
    9.  
    10.     public float maxRayCastRange = 500.0f;
    11.  
    12.     //general detection
    13.     public bool isDetected = false;
    14.     //can see target
    15.     public bool canSee = false;
    16.    
    17.     void OnTriggerStay(Collider other)
    18.     {
    19.         isDetected = true;
    20.         if (Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit))
    21.         //if (Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit, sightBlockingLayers))
    22.         //if(Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit, 100, sightBlockingLayers))
    23.         //if(Physics.Raycast(origin: transform.position, direction: (other.transform.position - transform.position), hitInfo: out hit, layerMask: sightBlockingLayers))
    24.         //if(Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit, maxRayCastRange, sightBlockingLayers))
    25.  
    26.         {
    27.             //if(hit.collider.gameObject.name == "Player")
    28.             if(other.gameObject.name == "Player")
    29.             {
    30.                 Debug.Log ("The " + other + " is staying in the collider");
    31.                 canSee = true;
    32.                 //Debug.Log ("I can see the " + other);              
    33.                 Debug.DrawLine (transform.parent.position, hit.point);
    34.             }
    35.         }
    36.     }
    37.  
    38.     /*void OnTriggerEnter(Collider other)
    39.     {
    40.  
    41.         if (Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit))
    42.         {
    43.             if(other.gameObject.name == "Player")
    44.             {
    45.                 Debug.Log ("The " + other + " entered the collider");
    46.                 isDetected = true;
    47.                 //Debug.Log ("I can see the " + other);              
    48.                 Debug.DrawLine (transform.parent.position, hit.point);
    49.             }
    50.         }
    51.     }*/
    52.  
    53.     void OnTriggerExit(Collider other)
    54.     {
    55.         isDetected = false;
    56.         if(other.gameObject.CompareTag("Player"))
    57.         {
    58.             Debug.Log("The " + other + " exited the collider");
    59.             canSee = false;
    60.         }
    61.     }
    62. }
    63.  
    I might try a new post on raycasting specifically and see what comes up.

    2h
     
  5. pixxelbob

    pixxelbob

    Joined:
    Aug 26, 2014
    Posts:
    111
    You're always just checking Collider other.
    You need to check the hit object from the raycast.

    (I haven't tested this but in theory it's what you need)
    I've refactored the methods a bit to clean up and separate concerns.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class PatrolDetection : MonoBehaviour {
    6.  
    7.     public bool isDetected { get; private set; }
    8.     public bool canSee { get; private set; };
    9.  
    10.     void Awake()
    11.     {
    12.         isDetected = false;
    13.         canSee = false;
    14.     }
    15.  
    16.     void OnTriggerEnter(Collider other)
    17.     {
    18.         // ignore collisions with anything other than the player collider.
    19.         if(!other.gameObject.CompareTag("Player"))
    20.             return;
    21.  
    22.         isDetected = true;
    23.         CheckSighting(other.gameObject);
    24.  
    25.     }
    26.  
    27.     void OnTriggerStay(Collider other)
    28.     {
    29.         // ignore collisions with anything other than the player collider.
    30.         if(!other.gameObject.CompareTag("Player"))
    31.             return;
    32.  
    33.         isDetected = true;
    34.         CheckSighting(other.gameObject);
    35.  
    36.     }
    37.  
    38.     void OnTriggerExit(Collider other)
    39.     {
    40.         // ignore collisions with anything other than the player collider.
    41.         if(!other.gameObject.CompareTag("Player"))
    42.             return;
    43.  
    44.         // we're not colliding with player so reset
    45.         isDetected = false;
    46.         canSee = false;
    47.     }
    48.  
    49.  
    50.     void CheckSighting(GameObject player)
    51.     {
    52.  
    53.         RaycastHit hit;
    54.         if (Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit))
    55.         {
    56.             if(hit.collider.gameObject.name == "Player")
    57.             {
    58.                 // Have line of sight to the player
    59.                 // This unit CAN see the player
    60.                 canSee = true;
    61.             }
    62.             else
    63.             {
    64.                 // No line of sight to the player
    65.                 // This unit CANNOT see the player
    66.                 canSee = false;
    67.             }
    68.         }
    69.     }
    70. }
    71.  
     
    Last edited: Feb 12, 2016
  6. LionFische

    LionFische

    Joined:
    Oct 16, 2015
    Posts:
    107
    Hi PBob, thanks again for the reply and the effort you put into it.

    I've tried that code and the results are similar to other methods.

    The detection picks up the player but no Raycast is drawn.

    2h
     
  7. LionFische

    LionFische

    Joined:
    Oct 16, 2015
    Posts:
    107
    Hi PBob, an update.

    I think I have found the issue and I think I made a silly omission.

    The detection script I had created had a public layerMask. I hadn't in the Inspector selected the component for the script and assigned the layerMask (with sightBlockingLayers) for the Walls (layer I created for the walls).

    I've now selected the component in the and the walls now seem to be blocking my Raycasts.

    Thank you for all the help. Without you guys I would have been lost.

    I've learnt a lot in the last few days on this issue.

    2h
     
  8. LionFische

    LionFische

    Joined:
    Oct 16, 2015
    Posts:
    107
    Spoke too soon...not working.

    2h