Search Unity

Question Can´t shoot NavMeh with raycast because it disables colliders

Discussion in 'Navigation' started by Gold_7, Jul 12, 2022.

  1. Gold_7

    Gold_7

    Joined:
    Jul 12, 2022
    Posts:
    9
    Hi I have made a basic project where you have to fight against AI. As an enemy I used the NevMeshAgent which works perfectly. for shooting I use the raycasting script from brackeys. My problem is that the raycast shoots through the NavMesh so the enemy does not take damage. I already tried to add more colliders also as a child of the actual object. Some how the NavMeshAgent disables those colliders. Also when I start the game I can shoot the enemy for maybe 30s after that I choot through it wich is really confusing. I did my best on finding a solution for this issu but I just did not manage to do so. Maybe someone can help me here....
    Thanks
     
  2. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    Are you considering a LayerMask when using these raycasts?

    I like to put my NavMesh on a seperate layer ("NavMesh") and the enemies on another ("Enemies"). That way I have more control over which layers the Raycast can actually "see". Logically, you will want your raycast to see both these layers. However, without seeing some code I'm not sure this is your issue. Could you post the code where you do the raycast? And could you tell us what the names are of the layers your enemies and navmeshes are on?

    This... shouldn't happen. What happens exactly: are child gameobjects set to disabled (greyed out) or are their colliders being disabled (the checkbox on the component becomes empty)? I suspect there's some code that "kills" the enemy that says "disable the collider/gameobject of whatever we hit". I went as as far as adding several hitzones per limb on a character that is a child of the NavMeshAgent gameobject, so I know for a fact objects that are children of NavMeshAgents can have their own colliders. The NavMeshAgent itself has none, although it's gizmo kinda looks like one.
     
  3. Gold_7

    Gold_7

    Joined:
    Jul 12, 2022
    Posts:
    9
    Thanks for trying to help me! I have the same Problem like this guy in the video:

    I don´t know why but when I start the game everything works as it should so I think my code is right. But after a few seconds I start on shooting through the enemys. However if I disable the NavMeshAgent everything works fine.
     
    nickicool likes this.
  4. Gold_7

    Gold_7

    Joined:
    Jul 12, 2022
    Posts:
    9
    the colliders are not disabled but after a few seconds thex stop working together with the Raycast which is caused by the NavMeshAgent
     
  5. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    I took a look at the video. Strange behavior indeed. One thing it doesn't show is the log. It might be that some error elsewhere prevents future code from executing. Is your log free of critical errors (those are the one that you can show/hide with the red button)?

    Could you paste the classes you have (ShootRays, ChangeColor, etc) in full, using the "insert code" button? I would like to compile this, so I can see for myself where it bugs out.

    Small tip: if you post these vids without maximizing the game screen, we could see the hierarchy and the log console. This helps other forum users help you debug.
     
  6. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    Ah, I think I got it. You forgot to "null check" your collider. You simply assumed any click would be on a collider. So if you are off by one pixel and click the background an exception would happen. Your code also assumed that it would have your component, so I added nullchecks for both. After all, we can click on everything in view. But not everything in view is guaranteed to have the collider, or the component. See if this helps:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ShootRays : MonoBehaviour
    6. {
    7.     public LayerMask mask;
    8.  
    9.     void Update()
    10.     {
    11.         if (Input.GetMouseButtonDown(0))
    12.         {
    13.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    14.             Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, mask);
    15.             Debug.DrawRay(hit.point, hit.normal, Color.green, 20f);
    16.             if (hit.collider)
    17.             {
    18.                 ChangeColors colors = hit.collider.gameObject.GetComponent<ChangeColors>();
    19.                 if (colors)
    20.                 {
    21.                     colors.Change();
    22.                 }
    23.              
    24.             } else
    25.             {
    26.                 // there is simply no collider, but the previous script assumed there was.
    27.                 // So if your click was a pixel off and you'd click the background, you'd
    28.                 // get an exception in your log.
    29.             }
    30.         }
    31.     }
    32. }
     
    Last edited: Jul 20, 2022
  7. Gold_7

    Gold_7

    Joined:
    Jul 12, 2022
    Posts:
    9
    I am not shure what you mean by that, thats the script I use for shooting:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Gun : MonoBehaviour
    4. {
    5.     public float damage = 10f;
    6.     public float range = 100f;
    7.     public float fireRate = 15f;
    8.  
    9.  
    10.     public Camera fpsCam;
    11.     public ParticleSystem muzzleFlash;
    12.     public ParticleSystem flash;
    13.     public AudioSource shoot;
    14.     public GameObject impacteffect;
    15.  
    16.     private float nextTimetoFire = 0f;
    17.  
    18.     void Update()
    19.     {
    20.         if (Input.GetButton("Fire1")&& Time.time >= nextTimetoFire)
    21.         {
    22.             nextTimetoFire = Time.time + 1f/fireRate;
    23.             Shoot();
    24.         }
    25.     }
    26.  
    27.     void Shoot()
    28.     {
    29.         RaycastHit hit;
    30.         muzzleFlash.Play();
    31.         flash.Play();
    32.         shoot.Play();
    33.        if(Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
    34.        {     if (hit.collider)
    35.             {
    36.                 Debug.Log(hit.transform.name);
    37.                 Target target = hit.transform.GetComponent<Target>();
    38.                 if (target != null && target != target.CompareTag("Player"))
    39.                 {
    40.                     target.TakeDamage(damage);
    41.  
    42.                 }
    43.                 GameObject impactGO = Instantiate(impacteffect, hit.point, Quaternion.LookRotation(hit.normal));
    44.                 Destroy(impactGO, 0.1f);
    45.             }
    46.        }
    47.     }
    48. }
     
  8. Gold_7

    Gold_7

    Joined:
    Jul 12, 2022
    Posts:
    9
    Also this is the code for my enemy. I know it is maybe not the best but normaly it works but after a few seconds it stops working as I said before. the enemy in my Scene has just a NavMeshAgent. The Player uses the First Person Controller from the starter assets and there is an other gameobject which is resposible for the Nav mesh surfice.
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.AI;
    4.  
    5. public class EnemyAi : MonoBehaviour
    6. {
    7.     public NavMeshAgent agent;
    8.  
    9.     public float throwforce = 40f;
    10.     public GameObject granadePref;
    11.  
    12.     public AudioSource clip;
    13.  
    14.     public ParticleSystem muzzleFlash;
    15.     public ParticleSystem flash;
    16.  
    17.     public Transform player;
    18.  
    19.     public LayerMask whatIsGround, whatIsPlayer;
    20.  
    21.     public float damage;
    22.     public bool granade;
    23.  
    24.     //Patroling
    25.     public Vector3 walkPoint;
    26.     bool walkPointSet;
    27.     public float walkPointRange;
    28.  
    29.     //Attacking
    30.     public float timeBetweenAttacks;
    31.     bool alreadyAttacked;
    32.  
    33.  
    34.     //States
    35.     public float sightRange, attackRange;
    36.     public bool playerInSightRange, playerInAttackRange;
    37.  
    38.     private void Awake()
    39.     {
    40.         player = GameObject.Find("FPSController").transform;
    41.         agent = GetComponent<NavMeshAgent>();
    42.     }
    43.  
    44.     private void Update()
    45.     {
    46.         //Check for sight and attack range
    47.         playerInSightRange = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
    48.         playerInAttackRange = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);
    49.  
    50.         if (!playerInSightRange && !playerInAttackRange) Patroling();
    51.         if (playerInSightRange && !playerInAttackRange) ChasePlayer();
    52.         if (playerInAttackRange && playerInSightRange) AttackPlayer();
    53.     }
    54.  
    55.     private void Patroling()
    56.     {
    57.         if (!walkPointSet) SearchWalkPoint();
    58.  
    59.         if (walkPointSet)
    60.             agent.SetDestination(walkPoint);
    61.  
    62.         Vector3 distanceToWalkPoint = transform.position - walkPoint;
    63.  
    64.         //Walkpoint reached
    65.         if (distanceToWalkPoint.magnitude < 1f)
    66.             walkPointSet = false;
    67.     }
    68.     private void SearchWalkPoint()
    69.     {
    70.         //Calculate random point in range
    71.         float randomZ = Random.Range(-walkPointRange, walkPointRange);
    72.         float randomX = Random.Range(-walkPointRange, walkPointRange);
    73.  
    74.         walkPoint = new Vector3(transform.position.x + randomX, transform.position.y, transform.position.z + randomZ);
    75.  
    76.         if (Physics.Raycast(walkPoint, -transform.up, 2f, whatIsGround))
    77.             walkPointSet = true;
    78.     }
    79.  
    80.     private void ChasePlayer()
    81.     {
    82.         agent.SetDestination(player.position);
    83.     }
    84.  
    85.     private void AttackPlayer()
    86.     {
    87.         //Make sure enemy doesn't move
    88.         agent.SetDestination(transform.position);
    89.         transform.LookAt(player);
    90.  
    91.         if (!alreadyAttacked)
    92.         {
    93.             RaycastHit hit;
    94.             if (Physics.Raycast(gameObject.transform.position, gameObject.transform.forward, out hit, attackRange))
    95.             {
    96.                 Debug.Log("schieße");
    97.                
    98.                 if(granade == true)
    99.                 {
    100.                     throwGranade();
    101.                 }
    102.                 else
    103.                 {
    104.                     muzzleFlash.Play();
    105.                     flash.Play();
    106.                     clip.Play();
    107.                 }
    108.                 Target target = hit.transform.GetComponent<Target>();
    109.                 if (target != null)
    110.                 {
    111.                     Debug.Log("Getroffen!!!");
    112.                     target.TakeDamage(damage);
    113.                 }
    114.  
    115.             }
    116.            
    117.             ///End of attack code
    118.  
    119.             alreadyAttacked = true;
    120.             Invoke(nameof(ResetAttack), timeBetweenAttacks);
    121.         }
    122.     }
    123.     private void ResetAttack()
    124.     {
    125.         alreadyAttacked = false;
    126.     }
    127.  
    128.     void throwGranade()
    129.     {
    130.         GameObject grenade = Instantiate(granadePref, transform.position, transform.rotation);
    131.         Rigidbody rb = grenade.GetComponent<Rigidbody>();
    132.         rb.AddForce(transform.forward * throwforce);
    133.     }
    134.  
    135.  
    136.  
    137.     private void OnDrawGizmosSelected()
    138.     {
    139.         Gizmos.color = Color.red;
    140.         Gizmos.DrawWireSphere(transform.position, attackRange);
    141.         Gizmos.color = Color.yellow;
    142.         Gizmos.DrawWireSphere(transform.position, sightRange);
    143.     }
    144. }
    145.  
     
  9. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    Your original code (which I retyped from the video) caused an error for me. It was due to the collider not being null checked, so if you clicked anywhere else you'd cause the error: and subsequent calls of the script would not be executed. I see your new code does that with:

    Code (CSharp):
    1. if (hit.collider)
    For me that null check prevented the error from happening. So I am not sure why its still bugging out, but I see a lot more code then I saw in the video. I would assume there's something else causing the error somewhere in the method body. Are there no critical errors in your log? Usually these point out in which code lines you can find the error.
     
  10. Gold_7

    Gold_7

    Joined:
    Jul 12, 2022
    Posts:
    9
    Yeah I know that is exactly what makes me freeking out haha there are no errors but after a few seconds killing th enemies doesn´t work
     
  11. Gold_7

    Gold_7

    Joined:
    Jul 12, 2022
    Posts:
    9
    I would uplaod the project so u can see it as well but I don´t know how ..
     
  12. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    Why not put it into a ZIP, upload it somewhere else and then provide us the link?
     
  13. nickicool

    nickicool

    Joined:
    Jan 19, 2022
    Posts:
    11
    I have the same problem. Have you found a solution?
     
  14. window_

    window_

    Joined:
    May 10, 2015
    Posts:
    9
    Just want to update if anyone is still facing same problem. I also had same issue and it fixed after removing the rigidbody