Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We’re making changes to the Unity Runtime Fee pricing policy that we announced on September 12th. Access our latest thread for more information!
    Dismiss Notice
  3. Dismiss Notice

Question Physics.OverlapSphere does not detect colliders unless it is touching their edges. Fix?

Discussion in 'Physics' started by undeadAlic3, Apr 14, 2023.

  1. undeadAlic3

    undeadAlic3

    Joined:
    Oct 13, 2022
    Posts:
    2
    Hi y´all, relatively new unity user here, have been making a small stealth game, and one of the mechanics involves turning off lights via hacking to make guards go and turn them on again. The way I envisioned this working is that using a field of view script on my enemy, which I have already tested on other objects with no failures to speak of, they would detect a collider I put on the level that matches the area that the light affects and go and turn it on. The issue I am running here is in the way I programmed the field of view.

    To give you some context here is the script I am using (The part where I check for a monobehavior object and then see what type it is, is subject to change but the actual functionality of detecting things via a field of view is definitive)

    Code (CSharp):
    1. void FindVisibleTargets()
    2.     {
    3.         Collider[] targetsInViewRadius = Physics.OverlapSphere(transform.position, viewRadius, targetMask);
    4.  
    5.         for (int i = 0; i < targetsInViewRadius.Length; i++)
    6.         {
    7.             Transform target = targetsInViewRadius[i].transform;
    8.             Vector3 dirToTarget = (target.position - transform.position).normalized;
    9.             if (Vector3.Angle(transform.forward, dirToTarget) - enemyUsingThis.patrol.transform.rotation.y < viewAngle / 2)
    10.             {
    11.                 float dstToTarget = Vector3.Distance(transform.position, target.position);
    12.                 _targetToLookOutFor = targetsInViewRadius[i].GetComponent<MonoBehaviour>();
    13.                 if (!Physics.Raycast(transform.position, dirToTarget, dstToTarget, obstacleMask))
    14.                 {
    15.                     if(targetToLookOutFor is DirectControlEntity)
    16.                     {
    17.                         HasSeenPlayer();
    18.                     }
    19.                    
    20.                     else if(targetToLookOutFor is SwitchLight)
    21.                     {
    22.                         HasSeenTurnedOffLight();
    23.                     }                                    
    24.                 }
    25.             }
    26.         }
    27.     }
    What I noticed though, due to the fact that the collider I use for the light is pretty big, is that Physic.OverlapSphere only detects the edges of a mesh rather than the inside meaning that if the entity with the field of view is entirely inside this collider, they won´t even detect that the light is off.

    I checked with IsOnTrigger and THAT will find a mesh even if the entity using the method is completely on the inside of the mesh and therefore no vertices of either collider are touching.

    Unfortunately, this is not what I am looking for as, within the context of the game, the guard should be able to see that a light has been turned off even if they aren´t directly on the part where the light is missing. Like when you are in a hallway and you only turn on the light closest to you but you can see the rest of the hallway being unilluminated.

    Hence I ask, what alternatives do I have? Are there any methods that can do the same as Physics.Overlap but can detect the inside of a collider or is there a better way to set up the field of view? Any answers would be apprciated.
     
  2. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,602
    Hi!

    I get a feel that your meshes are concave. Concave meshes in Unity (and most game engines) are not "solid": they have no volume, only their surface generates collisions. This is because calculating overlaps between arbitrary concave volumes is extremely expensive.

    Make sure your MeshColliders are convex. Or, define your light areas using multiple convex colliders, this is a typical trick used to make concave volumes out of several convex ones. That should allow you to check whether a sphere is completely inside of them or not.