Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Return gameobjects in array using OverlapCircle

Discussion in 'Scripting' started by Deleted User, Jun 25, 2017.

  1. Deleted User

    Deleted User

    Guest

    Hello, guys. I made my magnet PowerUp, I don't found in google easy way to made this and tried to made own magnet Power up. And it's ok! I made it :D But now I need to improve it, and I need your help, guys.

    There is part of my script:
    Code (CSharp):
    1. if (MagnetActivated)
    2.         {
    3.             MagnetTargets = GameObject.FindGameObjectsWithTag("Stuff");
    4.             foreach (GameObject Mtarget in MagnetTargets)
    5.             {
    6.                 Mtarget.transform.position = Vector3.MoveTowards(Mtarget.transform.position, transform.position, 0.2f);
    7.             }
    8.         }
    It magnetizes all objects with tag in Scene :D but I would like to made some radius/range to find these gameobjects. How I can do this? Maybe with help of OverlapCircle? If yes, how can I do this? Please, give me some advice :(
    Thx for attention :)
     
  2. Deleted User

    Deleted User

    Guest

    And one more question, I would like to find 2 tag's: Stuff and BigStuff. And put it in MagnetTargets array. But how can I do this? If I write
    Code (CSharp):
    1. FindGameObjectsWithTag("Stuff"&&"BigStuff");
    there is an error.
    So how can I make this?
     
  3. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    there's an overload for overlapcircle that fills an array you provide it with collider2d s.

    As for finding 2 lists, you have to do them separately, afaik.
     
  4. Deleted User

    Deleted User

    Guest

    Hello :)
    Nice to meet you again in my topic:)

    I understand about what you are talking. But I'm not strong in this yet, I'm just learning it all during making my first game :)
    I was looking in documentation, but I'm not pretty understand how to make OverlapCircle to return array of objects in it's range. I was using OverlapCircle im one of my script, but it's only returns like bool if there some objects. Can you give me some advices about this?
     
  5. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
  6. Deleted User

    Deleted User

    Guest

    Okay, I found it and thanks for this advice, I don't knew that I could see overloads like that in that way:)

    I don't understand what I need to write in ContactFilter2D? And is it possible to find objects in area with tags?
     
  7. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    you can just use a variable of type ContactFilter2D. If you want , you can change some properties on it, too.

    As for finding the objects with tags, you'd have to go over the list. That doesn't seem to be included in the filter.
    So, once you've gotten your array with its results, you can iterate the array and find the ones with tags that you want.
    Unless the tagged objects were on a unique layer, then yes you could do that - but that's because you can set the layer in the ContactFilter, I believe. Check the docs for its options :)
     
  8. Deleted User

    Deleted User

    Guest

    I've tried to type this:
    Code (CSharp):
    1. Physics2D.OverlapCircle(gameObject.transform.position, 3f, ContactFilter2D, Collider2D[] result);
    But there is errors in ContactFilter2D and array :( What I am doing wrong?
    I see all variables that are available, but is it possible to not use them?
     
    Last edited by a moderator: Jun 26, 2017
  9. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    You'd need to create new variables before using them in the method. You might be able to create the contactfilter2d in the call.
    Code (csharp):
    1.  
    2. ContactFilter2D cf;
    3. Collider2D [] result = new Collider2D[10]; // requires a size, it will return only up to a max of the size available.
    4. Physics2D.OverlapCircle(gameObject.transform.position, 3f, cf, result);
    5. // use result here
    6. // this might work , too
    7. Collider2D [] result = new Collider2D[10]; // requires a size, it will return only up to a max of the size available.
    8. Physics2D.OverlapCircle(gameObject.transform.position, 3f, new ContactFilter2D(), result);
    9.  
     
    Sounegi likes this.
  10. Deleted User

    Deleted User

    Guest

    In this part there is an error in " cf ":
    Code (CSharp):
    1. Physics2D.OverlapCircle(gameObject.transform.position, 3f, cf, result);
    If I do like this it's looks like with errors:
    Code (CSharp):
    1. Collider2D[] result = new Collider2D[10];
    2. Physics2D.OverlapCircle(gameObject.transform.position, 3f, new ContactFilter2D() , result);
     
  11. Deleted User

    Deleted User

    Guest

    I tried to made some code:
    Code (CSharp):
    1.             Collider2D[] result = new Collider2D[10];
    2.             Physics2D.OverlapCircle(gameObject.transform.position, 3f, new ContactFilter2D() , result);
    3.             foreach (Collider2D res in result)
    4.             {
    5.                 if (res.tag == "Stuff")
    6.                 {
    7.                     MagnetTargets = res;
    8.                 }
    9.             }
    There is problem because it cannot convert Collider2D in gameobject. MagnetTargets is array of GameObject. I need it because next I use:
    Code (CSharp):
    1. foreach (GameObject Mtarget in MagnetTargets)
    2.             {
    3.                 Mtarget.transform.position = Vector3.MoveTowards(Mtarget.transform.position, transform.position, 0.2f);
    4.             }
     
  12. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    You lost me a little bit. Did the code I wrote have errors or did it work?
    If none of it worked, we should probably fix that first.

    as for the second part, it would be a little easier if you rewrote MagnetTargets to be a list, rather than array.
    Then, when you find a match on the tag, do this:
    Code (csharp):
    1. MagnetTargets.Add(res.gameObject);
    Okay, I tested the code. Yes, the first one I wrote won't work, unless you did: ContactFilter2D cf = new ContactFilter2D();
    Which, if you use only the default settings, would be the same as making it new in the constructor.
     
    Deleted User likes this.
  13. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Before calling the overlap method, you can clear the array like so:
    Code (csharp):
    1.  System.Array.Clear(results, 0, 10); // where '10' is the array size, in this example. If you do "using System;" at the top of the script file, you can omit that from the beginning of this method, the "System." part
     
  14. Deleted User

    Deleted User

    Guest

    As I understand using "new ContactFilter2D()" it's like not using variables in it?
    I mean, is there some overload like this without filter? Because I don't see them :)
     
  15. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Not sure I understand your question. What the 'new ContactFilter2D()' does is just creates a new struct variable with the default values assigned and sends that into the function. These default values may be all you need. As I said in a different post, if you wanted to filter layers, you could create the variable before the function call, modify the filtered layers, and then send the variable into the function. Then, it would return a filtered array to you, with the desired layers.. Phew, hope that made sense :)

    There are only the 2 overloads for that function. The one we're talking about , and the one that returns only 1 hit.
    There is however this method: https://docs.unity3d.com/ScriptReference/Physics2D.OverlapCircleNonAlloc.html
    Its signature is a little different. You might prefer that one. To be honest, I'm pretty sure you can get what you want with either of the 2 that return array results. :)
     
  16. Deleted User

    Deleted User

    Guest

    I tried
    Code (CSharp):
    1. MagnetTargets.Add(res.gameObject);
    But there is an error in Add. I was tried to make new MagnetTargets array with fixed size, but problem still.

    Then I wrote the next:
    Code (CSharp):
    1. if (MagnetActivated)
    2.         {
    3.          
    4.             Collider2D[] result = new Collider2D[10];
    5.             Array.Clear(result, 0, 10);
    6.             Physics2D.OverlapCircle(gameObject.transform.position, 3f, new ContactFilter2D() , result);
    7.             foreach (Collider2D res in result)
    8.             {
    9.                 if (res.gameObject.tag == "Stuff")
    10.                 {
    11.                     magnetobj.Add(res.gameObject);
    12.                     foreach (GameObject mobj in magnetobj)
    13.                     {
    14.                         mobj.transform.position = Vector3.MoveTowards(mobj.transform.position, transform.position, 0.2f);
    15.                     }
    16.                 }
    17.             }
    18.         }
    And the array and list code in the start of class:
    Code (CSharp):
    1. public Collider2D[] result;
    2.  
    3.     public GameObject[] MagnetTargets;
    4.     public List<GameObject> magnetobj = new List<GameObject>();
    All seems like withoud errors but in game, after I take magnet PowerUp Unity writes me that in this part:
    Code (CSharp):
    1.                 if (res.gameObject.tag == "Stuff")
    error:NullReferenceException: Object reference not set to an instance of an object

    The problem as I think in that it couldn't convert Collider2D in GameObject?
     
  17. Deleted User

    Deleted User

    Guest

    Now I thought to try new way like:
    Code (CSharp):
    1. if (MagnetActivated)
    2.         {
    3.             //MagnetTargets = GameObject.FindGameObjectsWithTag("Stuff");
    4.  
    5.             Collider2D[] result = new Collider2D[10];
    6.             Array.Clear(result, 0, 10);
    7.             Physics2D.OverlapCircle(gameObject.transform.position, 3f, new ContactFilter2D() , result);
    8.             foreach (Collider2D res in result)
    9.             {
    10.                 GameObject obj = res.gameObject;
    11.                 if (obj.tag == "Stuff")
    12.                 {
    13.                     obj.transform.position = Vector3.MoveTowards(obj.transform.position, transform.position, 0.2f);
    14.                 }
    15.             }
    16.         }
    But the problem still in:
    Code (CSharp):
    1. GameObject obj = res.gameObject;
     
  18. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Okay, let's step through this.. there are several things that could be changed or maybe changed.
    1) Do you use the array of MagnetTargets at all? If not, no need for that array.
    2) There is no need to clear the array right after you've made it - b/c it's obviously empty to begin with. I only wrote that code for you if you re-use the array. In other words, only if you declare it outside of the function, but re-use it on calls to that function, then you should clear it.
    3) you should either do: a) a for loop like : for (int i = 0; i < #_of_Colliders_returned; ++i) or b) check that it isn't null when you're trying to get your game object "res.gameObject"
    ** the reason is the list will have 10 null entries, if it doesn't find anything. if you do:
    Code (csharp):
    1.  
    2. int num = Physics2D.OverlapCircle(gameObject.transform.position, 3f, new ContactFilter2D() , result);
    3.  
    now 'num' will have how many it got.

    4) do not loop the list until you've gone through the 'result' array and added all of the appropriate objects. Only after the list is full should you interate over it and do your moves. Otherwise you'll do the earlier ones in the list more times..

    Hopefully all of that makes sense :)
     
  19. Deleted User

    Deleted User

    Guest

    List was needed as, I thought, in my previous method, because some part of code wasn't working.
    I checked how many there are "num's" - there are 3 or more. But problem in part "GameObject obj = res.gameObject;" still remain.
    I created a reference to the object, to which other object must be moved, because for the moment I thought that the problem in it... But no :(


    Code (CSharp):
    1. {
    2.             Collider2D[] result = new Collider2D[10];
    3.             int num = Physics2D.OverlapCircle(gameObject.transform.position, 50f, new ContactFilter2D() , result);
    4.             print("num"+num);
    5.             foreach (Collider2D res in result)
    6.             {
    7.                 GameObject obj = res.gameObject;
    8.                 if (obj.tag == "Stuff")
    9.                 {
    10.                     obj.transform.position = Vector3.MoveTowards(obj.transform.position, Char.transform.position, 0.2f);
    11.                 }
    12.             }
    13.         }
     
  20. Deleted User

    Deleted User

    Guest

    I tried to simplify this code little bit to resolve problem easier:
    Code (CSharp):
    1. if (MagnetActivated)
    2.         {
    3.             Collider2D[] result = new Collider2D[10];
    4.             int num = Physics2D.OverlapCircle(gameObject.transform.position, 50f, new ContactFilter2D() , result);
    5.             print("num"+num);
    6.             foreach (Collider2D res in result)
    7.             {
    8.                 if (res.gameObject.tag == "Stuff")
    9.                 {
    10.                     res.transform.position = Vector3.MoveTowards(res.transform.position, Char.transform.position, 0.2f);
    11.                 }
    12.             }
    13.         }
    Now problem in "if (res.gameObject.tag == "Stuff")" it writes in Unity that Object reference not set to an instance of an object. I don't understand in what object can be this problem :mad: Maybe something wrong with the array?
     
  21. Deleted User

    Deleted User

    Guest

    Now I tried to delete tag check and it works. It magnetizes objects, but for some reason it magnetizes only obstacles :D:D
    Maybe the reason in that the my stuff that I need to magnetize is trigger? Obstacles not triggers.

    Maybe this OverlapCircle don't detects triggers?
     
  22. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Okay, few things here.. How does this code execute (just curious?) Like when you push a button / key?

    Second thing. As I tried to tell you about some can be null, you have to either check for null or only loop the # of results found. In your example, you made a half decision to get the # of objects detected, but then you never used that number for anything practical (you printed it but didn't use it in a loop).

    As for your new "issue". Yes, you have to create a ContactFilter2D that queries triggers. Send that into the method, and then it should be working :)

    ** And you can put the 'tag' check back in when you have those 2 parts working correctly, of course.
     
  23. Deleted User

    Deleted User

    Guest

    Yes, if it will works :)
    Now I made as you say, if I correct understand you about using num:
    Code (CSharp):
    1. if (MagnetActivated)
    2.         {
    3.             Collider2D[] result = new Collider2D[10];
    4.             int num = Physics2D.OverlapCircle(gameObject.transform.position, 50f, new ContactFilter2D() , result);
    5.             print("num"+num);
    6.             if (num != 0)
    7.             {
    8.                 foreach (Collider2D res in result)
    9.                 {
    10.                         res.transform.position = Vector3.MoveTowards(res.transform.position, Char.transform.position, 0.2f);
    11.                 }
    12.             }
    13.         }
    Now I'm looking for how to correctly write ContactFilter2D.useTriggers but can't find information about it :)
     
  24. Deleted User

    Deleted User

    Guest


    Hooray, I made it, now it moves all object and triggers to :)
    Code (CSharp):
    1. if (MagnetActivated)
    2.         {
    3.             Collider2D[] result = new Collider2D[10];
    4.             ContactFilter2D filter = new ContactFilter2D();
    5.             filter.useTriggers = true;
    6.             int num = Physics2D.OverlapCircle(gameObject.transform.position, 50f, filter , result);
    7.             print("num"+num);
    8.             if (num != 0)
    9.             {
    10.                 foreach (Collider2D res in result)
    11.                 {
    12.                         res.transform.position = Vector3.MoveTowards(res.transform.position, Char.transform.position, 0.2f);
    13.                 }
    14.             }
    15.         }
    It seem crazy now, because it moves even background images :D:D:D
    Now I will try to make filter by tag :)
     
  25. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ya, try the tag thing. but that's not what I meant about the num thing.
    I meant like this:
    Code (csharp):
    1.  
    2. for(int i = 0; i < num; ++i) {
    3.    if(result[i].CompareTag("Stuff")) {
    4.       result[i].transform.position = Vector3.MoveTowards(res.transform.position, Char.transform.position, 0.2f);
    5.       }
    6.    }
    7.  
     
  26. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    It's worth noting that, if you're calling this from Update(), there are some improvements that you could make. Another time, though.. hopefully you'll have it working as is, soon, with the modifications. =)
     
    Deleted User likes this.
  27. Deleted User

    Deleted User

    Guest

    I made tag check as you say and made yours improvement :)
    Now it works fine as I want. Thank you for your help again, now I know one more thing in coding :)
     
  28. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Cool :) Glad ya got it working.
     
    Deleted User likes this.