Raycast going through other objects

Hi I am having a problem with Raycasting.

I have a player character represented by a cube and a patrol represented by another cube. The patrol cycles through waypoints while the player is free to walk around.

Attached to the Patrol cube I have another cube, set to act as a detection zone. When this zone is triggered, the patrol cube attempts to locate the player and fire a raycast at the player. This is being successfully achieved.

However the issue is, I want the player to be able to then move and hide itself from the view of the patrol. So when the player has an object positioned between itself and the patrol, the raycast can not see the player.

The code I am using according to the documents should not pass a ray through other objects with Colliders, however my code is doing just that.

(I have tried a few variations, so some of these are still there and commented out).

The Code

using UnityEngine;
using System.Collections;

public class PatrolDetection : MonoBehaviour {

    public LayerMask sightBlockingLayers;

    public RaycastHit hit;

    public float maxRayCastRange = 500.0f;

    //general detection
    public bool isDetected = false;
    //can see target
    public bool canSee = false;
   
    void OnTriggerStay(Collider other)
    {
        isDetected = true;
        if (Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit))
        //if (Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit, sightBlockingLayers))
        //if(Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit, 100, sightBlockingLayers))
        //if(Physics.Raycast(origin: transform.position, direction: (other.transform.position - transform.position), hitInfo: out hit, layerMask: sightBlockingLayers))
        //if(Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit, maxRayCastRange, sightBlockingLayers))

        {
            //if(hit.collider.gameObject.name == "Player")
            if(other.gameObject.name == "Player")
            {
                Debug.Log ("The " + other + " is staying in the collider");
                canSee = true;
                //Debug.Log ("I can see the " + other);               
                Debug.DrawLine (transform.parent.position, hit.point);
            }
        }
    }

    /*void OnTriggerEnter(Collider other)
    {

        if (Physics.Raycast(transform.position, (other.transform.position - transform.position), out hit))
        {
            if(other.gameObject.name == "Player")
            {
                Debug.Log ("The " + other + " entered the collider");
                isDetected = true;
                //Debug.Log ("I can see the " + other);               
                Debug.DrawLine (transform.parent.position, hit.point);
            }
        }
    }*/

    void OnTriggerExit(Collider other)
    {
        isDetected = false;
        if(other.gameObject.CompareTag("Player"))
        {
            Debug.Log("The " + other + " exited the collider");
            canSee = false;
        }
    }
}

This has me stuck, any advice would be most appreciated!

2h

so… canSee is never set back to false unless the player leaves the trigger?

You have to use RayCastHit and create an obstacle or a hidden layer and assisng it to a layerMask like :

public LayerMask hiddenMask;//assign in Inspector

RayCastHit checkHidden;

//set what checkHidden hits

if(hit)
{
      canSee = false;
}

Should work, at school so I cant test it for you.

Hi BDaddy. Thank you for the advice.

I don’t completely understand your suggestion. If you have time I’d appreciate if you could go into a little more detail.

2h

Hi BDaddy, I think I have the issue sorted. With help from other forum members, I was working with the layers also and I think in a similar way to the one you suggested.

Anyway, my mistake was a silly one. I hadn’t gone to the Inspector component for my script and selected the layerMask layer. Other then that, I think it was functioning okay.

I’m testing now, it seems to be functioning. Fingers crossed.

Thank you for the suggestion,

2h

I think there is room for improvement in the logic of your work here.

Check out the changes I have made to your original script and see if the logic works better.

public class PatrolDetection : MonoBehaviour
{

    public LayerMask sightBlockingLayers;

    public RaycastHit hit;

    public float maxRayCastRange = 500.0f;

    //general detection
    public bool isDetected = false;
    //can see target
    public bool canSee = false;

    void OnTriggerStay(Collider other)
    {
        if (!other.gameObject.CompareTag("Player"))
            return;

        canSee = false;
        Ray ray = new Ray(transform.position, other.transform.position - transform.position);
        if (Physics.Raycast(ray, out hit, maxRayCastRange))
        {
            if (hit.collider == other)
            {
                Debug.Log("The " + other + " is staying in the collider");
                canSee = true;
                Debug.DrawLine(transform.parent.position, hit.point);
            }
        }
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Player"))
            isDetected = true;
    }

    void OnTriggerExit(Collider other)
    {
        if (other.gameObject.CompareTag("Player"))
        {
            isDetected = false;
            canSee = false;
            Debug.Log("The " + other + " exited the collider");
        }
    }
}

Hi Bob, tried that but not working.

I’m not sure what has gone wrong, my patrol has now also stopped following my player, Nightmare! I have two scripts.

The moveEnemy is dependent on the canSee bool.

using UnityEngine;
using System.Collections;
//This allows for the use of lists
using System.Collections.Generic;

public class PatrolController : MonoBehaviour {
   
    public List<Transform> wayPointsList = new List<Transform>();

    public Transform currentWaypoint;

    public Transform currentPatrolTarget;

    public int wayPointNumber = 0;
   
    public float speed =4f;

    public float turnSpeed = 1f;

    public PatrolDetection PT;

    //NavMeshAgent Componants -> Navigation
    public NavMeshAgent navAgent;

    // Use this for initialization
    void Start () {
        currentWaypoint = wayPointsList [wayPointNumber];
    }
   
    // Update is called once per frame
    void Update () {
        moveEnemy ();
    }
   
    public void moveEnemy()
    {
        if (GameObject.Find ("Player") != null && PT.canSee == true)
        {
            Debug.Log ("The Player is detected seen!");
            currentPatrolTarget = GameObject.Find ("Player").transform;
            navAgent.SetDestination(currentPatrolTarget.position);
        }
        else
        {
            if(navAgent.remainingDistance <= navAgent.stoppingDistance)
            {
                if (wayPointNumber != wayPointsList.Count - 1) {
                    wayPointNumber++;
                    navAgent.SetDestination(wayPointsList [wayPointNumber].position);
                }
                else
                {
                    wayPointNumber = 0;
                    navAgent.SetDestination(wayPointsList [wayPointNumber].position);
                }   

            }
        }
    }

}

The other script I have reverted back as the suggested way was producing similar results.

2h

Got the Patrol back tracking me…still casting through walls though.

OK, I see your problem. I did re-write what you had to make it a little simpler.

You get the frist waypoint, but never set the navAgent’s destination. So obviously, it is never close to the destination, so it never gets started.

public class PatrolDetection : MonoBehaviour
{

    public float maxRayCastRange = 500.0f;

    public Transform target;

    void OnTriggerStay(Collider other)
    {
        target = null;
        if (!other.gameObject.CompareTag("Player"))
            return;

        RaycastHit hit;
        Ray ray = new Ray(transform.position, other.transform.position - transform.position);
        if (Physics.Raycast(ray, out hit, maxRayCastRange))
        {
            if (hit.collider == other)
            {
                target = other.transform;
                Debug.DrawLine(transform.parent.position, hit.point);
            }
        }
    }

    void OnTriggerExit(Collider other)
    {
        if (other.gameObject.CompareTag("Player"))
        {
            target = null;
            Debug.Log("The " + other + " exited the collider");
        }
    }
}

public class PatrolController : MonoBehaviour
{
    public List<Transform> wayPointsList = new List<Transform>();
    public Transform currentWaypoint;
    public Transform currentPatrolTarget;
    public int wayPointNumber = 0;
    public float speed = 4f;
    public float turnSpeed = 1f;
    private bool chasing = false;

    public PatrolDetection PT;

    //NavMeshAgent Componants -> Navigation
    public NavMeshAgent navAgent;

    // Use this for initialization
    void Start()
    {
        currentWaypoint = wayPointsList[wayPointNumber];
        navAgent.SetDestination(currentWaypoint.position);
    }

    // Update is called once per frame
    void Update()
    {
        moveEnemy();
    }

    public void moveEnemy()
    {
        if (PT.target != null)
        {
            navAgent.SetDestination(PT.target.position);
            chasing = true;
        }
        else
        {
            if (chasing) {
                navAgent.SetDestination(currentWaypoint.position);
                chasing = false;
            }
            if (navAgent.remainingDistance <= navAgent.stoppingDistance)
            {
                wayPointNumber = (++wayPointNumber) % wayPointsList.Count;
                currentWaypoint = wayPointsList[wayPointNumber];
                navAgent.SetDestination(currentWaypoint.position);
            }
        }
    }
}

Hi Big.

I’ve actually got the nav back working. I’ve had a look at your script and tried it but it’s not causing the patrol to follow the player.

The issue now is the raycast. It’s still going through walls.

Thank you for the help. I hope we can get to the bottom of this!

2h