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. Dismiss Notice

Question Having an issue with OverLapSphere

Discussion in 'Scripting' started by Clydey2Times, Jan 22, 2022.

  1. Clydey2Times

    Clydey2Times

    Joined:
    Oct 24, 2017
    Posts:
    232
    Hey all. I'm no doubt missing something incredibly obvious here, but the below if statement isn't working as intended. When I am out of range of the object, I expect the else part to be executed, but for some reason it isn't happening.

    I have essentially the same code as below on another object (it detects the player instead of the other way around) and it works fine. As soon as the player leaves the sphere, the else is called. I can't figure out why it isn't working in this case.

    Is it an issue with my temp variable? Any help is appreciated.

    Code (CSharp):
    1.  private void OverLapSphere()
    2.     {
    3.         Collider[] hitColliders = Physics.OverlapSphere(transform.position, 1, pickup);
    4.  
    5.         foreach (Collider c in hitColliders)
    6.         {
    7.             if (c.tag == "Pickup")
    8.             {
    9.                 canInteractWithItem = true;
    10.                 currentItemCollider = c;
    11.              
    12.             }
    13.             else
    14.             {
    15.                 canInteractWithItem = false;
    16.                 currentItemCollider = null;
    17.                 yesNoCanvas.enabled = false;
    18.             }
    19.         }
    20.     }
     
    Last edited: Jan 22, 2022
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Your logic is to gather everything you overlap, then process what you overlapped.

    So ... right away if you don't overlap anything at all, line 5 will loop zero times, hence the else won't execute.

    Do you mean to perhaps have something like:

    Code (csharp):
    1. if (hitColliders.Length > 0)
    2. {
    3.   // process overlaps by looping them all
    4. }
    5. else
    6. {
    7.    // nope, nuthin' overlapped
    8. }
     
  3. Clydey2Times

    Clydey2Times

    Joined:
    Oct 24, 2017
    Posts:
    232
    I had considered that, but as I said, I have almost identical code on another object and it works perfectly. It detects the player and the first part of the if statement runs. The player leaves the sphere, the else part runs.

    It's identical for all intents and purposes. When the player leaves the sphere, there are zero colliders to process (the player is the only one tagged as such and is the only object on the player layer). Why would the else part be executed in the latter case?

    The only difference is that in one case it looks for a "Player" tag and in the other case it looks for a "Pickup" tag. So I'm very confused. I can certainly change my code to work around it, but I'd like to understand what the difference is between the two cases. Any ideas?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    You should fix that... here is how to understand why the two identical pieces of code behave differently.

    I highly recommend you take the time to understand your code's current behavior because it will make your brain grow a few sizes larger. That plus you'll sleep better!

    You must find a way to get the information you need in order to reason about what the problem is.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also put in Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target.

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494
     
  5. Clydey2Times

    Clydey2Times

    Joined:
    Oct 24, 2017
    Posts:
    232
    I'm not entirely new to coding, so the first couple of paragraphs were bizarrely condescending. I have used debug.log to check what is running and when it is running. The code is running exactly as I said. In the following piece of code, the else is being executed on every frame in which the player is outside of the overlap sphere. Again, I checked this. The debug.log message fires off continuously.

    Code (CSharp):
    1. private void OverLapSphere()
    2.     {
    3.         Collider[] hitColliders = Physics.OverlapSphere(transform.position, 1, player);
    4.  
    5.         foreach (Collider c in hitColliders)
    6.         {
    7.             if (c.tag == "Player")
    8.             {
    9.                 canInteractWithItem = true;
    10.              
    11.            
    12.             }
    13.             else
    14.             {
    15.                 canInteractWithItem = false;
    16.                 Debug.Log("Howdy");
    17.              
    18.             }
    19.         }
    20.     }
    In the following piece of code, the else part of the if statement *isn't* being executed. Again, I have used debug.log to confirm this. I have also checked every object to make sure they don't have the wrong tag or layer.

    Code (CSharp):
    1.  private void OverLapSphere()
    2.     {
    3.         Collider[] hitColliders = Physics.OverlapSphere(transform.position, 1, pickup);
    4.         foreach (Collider c in hitColliders)
    5.         {
    6.             if (c.tag == "Pickup")
    7.             {
    8.                 canInteractWithItem = true;
    9.                 currentItemCollider = c;
    10.            
    11.             }
    12.             else
    13.             {
    14.                 canInteractWithItem = false;
    15.                 currentItemCollider = null;
    16.                 yesNoCanvas.enabled = false;
    17.             }
    18.         }
    19.     }
    I appreciate you trying to help, but I cannot see why one works but the other doesn't. There obviously is a reason. I'm just asking for help in identifying what it might be, as the reason you offered in your first response doesn't seem to be the issue.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Don't take offense. It's my standard "here's how to learn" blurb. Every single thing on there is something that has happened right her in this forum enough times that I didn't want to type it again.

    Whatever it is, if your hitColliders truly is an empty collection, the entire if/else will not fire.

    I think you are colliding with something that isn't a "player" or isn't a "pickup"

    Prove me wrong.
     
  7. Clydey2Times

    Clydey2Times

    Joined:
    Oct 24, 2017
    Posts:
    232
    No worries. I'm probably a little oversensitive if I feel someone is talking down to me.

    So I removed the layermask from the parameters. The overlap sphere straight up didn't work without it. Not sure why. It's 4.30am, so I didn't investigate too much.

    I also added an extra check, as I think you suggested. I wrapped the foreach in a: if(hitColliders != null). That didn't seem to work either. I'm truly at a loss here. I can't identify a single salient difference between the two. I'll take the relevant objects into an empty scene tomorrow and see if that sheds any light.

    Edit: realised the null check might not work, so changed to checking length(as you suggested) and that seems to do the trick. I now just need to figure out why the collider array isn't empty once my player is out of range of the object.
     
    Last edited: Jan 23, 2022