Search Unity

OverlapSphere and OverlapSphereNonAlloc

Discussion in 'Scripting' started by 90okm, Feb 27, 2017.

  1. 90okm

    90okm

    Joined:
    Nov 26, 2013
    Posts:
    5
    Hi ! what is the difference between OverlapSphere and OverlapSphereNonAlloc ?

    It's been said that OverlapSphereNonAlloc does almost the same but generates less garbage.

    Does it mean that it's more efficient in sense of performance ?
    There is no an example of implementation of OverlapSphereNonAlloc method in docs. But it seems different from OverlapSphere

    In what cases i should use OverlapSpere instead of OverlapSphereNonAlloc and vice versa ?

    Thanks in advance !
     
  2. AverageProg

    AverageProg

    Joined:
    Jun 25, 2015
    Posts:
    38
    Eache time you call overlapSphere that code will allocate a new array.

    You could optimize this by keeping the same fixed size array and calling overlapSphereNonAlloc instead.

    If you notice the method returns the number of colliders hit, so presumably you should pass in a pre-allocated array big enough to store the results, I sincerely don't know what would happen if you don't pass a big enough array.
     
  3. 90okm

    90okm

    Joined:
    Nov 26, 2013
    Posts:
    5
    Thanks !
    As far as i understood that fixed array will be rewritten each time i call OverlapSphereNonAlloc method ?
     
  4. AverageProg

    AverageProg

    Joined:
    Jun 25, 2015
    Posts:
    38
    yes, supposedly only up to the return value of the method.

    You need to experiment with it a little bit as the documentation is, as always, a little bit lacking.
     
    Walter_Hulsebos likes this.
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    OverlapSphere finds all the overlapping colliders, creates a new array, puts the colliders inside of it, and returns that array.

    For OverlapSphereNonAlloc, you send in an array, it finds all the overlapping colliders, puts them in the array, and returns how many colliders it found.

    So for OverlapSphereNonAlloc, you can re-use the same array for subsequent calls to the same method. OverlapSphere generates a new array each time.


    OverlapSphereNonAlloc is generally a better solution, since it doesn't generate new arrays that slowly fills the memory (causing GC spikes when you run out). There's some downsides, though:
    - The remaining spaces in the array is not changed, so you have to be careful to only read up to the returned number from the array.
    - If you send in a too small array, you'll miss data. The order of the returned colliders are not documented, and I doubt it's consistent, so you might lose the most important results.

    OverlapSphereNonAlloc example:

    Code (csharp):
    1. private Collider[] overlapResults = new Collider[10];
    2.  
    3. private void Update() {
    4.     int numFound = Physics.OverlapSphereNonAlloc(transform.position, 10f, overlapResults);
    5.  
    6.     for (int i = 0; i < numFound; i++) {
    7.         Debug.DrawLine(transform.position, overlapResults[i].transform.position, Color.red);
    8.     }
    9. }
     
    Last edited: May 8, 2020
  6. 90okm

    90okm

    Joined:
    Nov 26, 2013
    Posts:
    5
    Well ! So it seems that OverlapSphereNonAlloc is more efficient in comparison to OverlapSphere.
    For garbage collector loading at least....

    Are there any situations where using of OverlapSphere is more reasonable ?
     
  7. AverageProg

    AverageProg

    Joined:
    Jun 25, 2015
    Posts:
    38
    I sometimes fail to see why people keep answering already answered questions.

    We are not in school anymore boy.
     
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    Sometimes because they didn't see a previous post.

    Sometimes because they want to give a more in depth answer.

    Sometimes because OP has more questions, or still doesn't fully understand it.

    Don't worry ZZantal, were not in school anymore, we don't need to get bothered because someone else also answered the question at hand.

    ...

    As for OP's latest inquiry:
    If you're not doing repeated OverlapSphere calls, you probably won't cache an array. In which case it's extra lines of code to create the array, call OverlapSphereNonAlloc, and then toss it out. Might as well just let OverlapSphere create the array.

    Also, allowing OverlapSphere in this scenario create said array, it guarantees the array is large enough to fit all results.
     
  9. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    There's aren't any examples or much explanation since allocating vs. non-allocating functions are standard features of programming (google them!) Unity's alloc/non-alloc stuff works the regular way. Not having an example is sort of a way to tell you "if you don't already know how to use this, it's better you don't."

    Sure, the purpose of nonallocate is to run a little faster _in certain situations_. But it's usually not much gain, it takes a while to learn how, Unity-forums aren't very good at teaching ComSci tricks (the rest of the internet is fine for it,) and there are probably a lot of much easier tricks to learn that give much better code improvements.

    But, if you want to learn "advanced" programming, definitely write down alloc v. non-alloc on one of your notecards and stick it on the bottom of the pile.
     
  10. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Strictly speaking its purpose is not to run faster even if that happens to be an additional gain. Sure, allocations take time, on the other hand the Non-Alloc has to perform various safety-checks.

    It's all about avoidable garbage in the first place.
     
    DotusX, Aethenosity, Ksanone and 5 others like this.
  11. 90okm

    90okm

    Joined:
    Nov 26, 2013
    Posts:
    5
    Thanks to All of You guys !
    it became clear for me.....
     
  12. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    I'm saying garbage is an unimportant detail. My point is the main things we care about are "Is is simpler and less error-prone?" or "Does it let me do something I couldn't do otherwise?" or the least important "does it run faster?" Out of those, nonAlloc is the last.

    Garbage seems to be one of those explanations which just makes things less clear. You get people worrying about it so much they try to avoid new Vector3 (which doesn't create any sort of garbage.) Plus, I assume Unity has some sort of modern generational garbage system, where there are different types of garbage and short-term isn't the bad kind.
     
  13. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You would be wrong here. Garbage is a very important performance consideration for any dev working with Unity. Remember we aren't in an enterprise situation where a few millisecond delay is acceptable. At 60 FPS you have exactly 16.7ms to do everything in a frame. A garbage collection can easily eat enough of your frame budget to cause a noticeable stutter.

    You would be wrong again. Unity's running on an old version of Mono, with an ancient garbage collector. That means every collection scans all of the heap memory.
     
  14. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    The non allocate method requires you as a developer to write more boilerplate code. So the regular method is faster to develop with.

    Plus sometimes you can't sensibly reuse the array. If you only call OverlapSphere once, there is no real point to using non allocate.

    Finally the non allocate method is more prone to errors. You can send in an array that's too small, and loose data. You can loose track of where should end the array, and thus use data from a previous run. Or you can replace an array before you are finished with it, thus using data from a future run.

    All said, if you don't need the performance, use the regular method. Non allocate should only be used if you need the performance.
     
    Hades714, Novack and davudovArtur like this.
  15. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,336
    Nope, mark-and-sweep. No generations for you!

    It's apparently being worked on together with the rest of the language upgrade stuff, but there's no official timeline yet for when we get a GC that's not decades old.
     
    phobos2077, Alverik and Kiwasi like this.
  16. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    When called regularly, it is indeed an important detail. If you call it once in a while, just call the allocating version.

    In regards to your list, it's quite the complete opposite:
    It's not simpler: You have to pass an array which should not be null, should be big enough unless you wanna miss results, you should handle the correct further usage of that array instance...
    which makes it more error prone.
    On top of that it doesn't allow to do something that the allocating version couldn't do, except that it avoids garbage.
    And it's also not necessarily faster.

    It's really only about the allocations, that's where its name originates from.

    That almost implies the name itself makes it less clear?

    It's sometimes better to worry a little more than less, given that you actually take the time to look things up in order to decide whether your worries are justified or not.

    In your example, one would pretty quickly realize that it's not an issue and that it might be possible to have missed a fundamental yet important difference between a reference type and a value type.

    And Unity's garbage collector: like already mentioned... don't count on that. :D
     
  17. gigazelle

    gigazelle

    Joined:
    May 6, 2017
    Posts:
    13
    Realizing this is a 3-year old necro, this thread is at the top of search results when comparing the difference between
    Physics.OverlapSphere
    and
    Physics.OverlapSphereNonAlloc
    . @Baste's relatively recent edits worked perfectly for me.

    I wanted to add a pretty important use case for
    Physics.OverlapSphereNonAlloc
    , and that is for when you want a super-performant OverlapSphere and you don't care about the Collider(s) in question, but rather that it simply collided with something. Assign the objects you want to listen for in a layer, then have
    Physics.OverlapSphereNonAlloc
    use that layer in a layer mask.

    Code (CSharp):
    1.  
    2. int numberOfColliders;
    3. Collider[] littleArray = new Collider[1];
    4.  
    5. void myFunction() {
    6. // sphereObject is where you want the center of the sphere; 1f is a float for the radius; littleArray is just there to store any one of the colliders; 1 << 2 is the layer mask (in this example, layer 2)
    7. numberOfColliders = Physics.OverlapSphereNonAlloc(sphereObject.transform.position,1f, littleArray, 1 << 2, QueryTriggerInteraction.Collide);
    8.             if (numberOfColliders > 0) {
    9.                    Debug.Log("Triggered with an object in layer 2");
    10.             }
    11. }
    12.  

    Edit:
    Physics.CheckSphere
    works a ton better.

    Code (CSharp):
    1.  
    2. // sphereObject is where you want the center of the sphere; 1f is a float for the radius; 1 << 2 is the layer mask (in this example, layer 2)
    3. if(Physics.CheckSphere(sphereObject.transform.position,1f, 1 << 2, QueryTriggerInteraction.Collide) {
    4.   Debug.Log("Triggered with an object in layer 2");
    5. }
    6.  
     
    Last edited: Aug 22, 2020
    Rejutka likes this.
  18. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    If you just want to know if something/anything is in the sphere... you could just use 'CheckSphere':
    https://docs.unity3d.com/ScriptReference/Physics.CheckSphere.html

    No array needed at all.
     
    Oelson, Rejutka, Olipool and 2 others like this.
  19. gigazelle

    gigazelle

    Joined:
    May 6, 2017
    Posts:
    13