Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Wrymnn · Nov 24, 2014 at 10:22 PM · hashtable

Remove from HashSet while Looping

Hi

I need to Loop through HashSet, and when condition is met, I need to remove those particular objects from the HashSet, but ofc it`s getting me error that I`m removing stuff from hashset while I`m iterating over it.

I tried this, but the same error it "foreach" line.

 HashSet<GameObject> temporaryMyObjects = myObjects; //myObjects is HashSet 
 
         foreach (GameObject Object in myObjects)
         {
             if (Object == player) { continue; }
 
             Vector2 distance = Object.transform.position - player.transform.position;
 
             if (distance.magnitude > 5000)
             {
                 Object.SetActive(false);
                 temporaryMyObjects .Remove(Object);
             }
         }
         myObjects= temporaryMyObjects ;

Any idea please? I think this should work, but it still says I`m tryin to modify it, even if I`m modifying some other hashset.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
4
Best Answer

Answer by Uldeim · Nov 24, 2014 at 11:00 PM

Unfortunately, HashSets are reference types. Assignment (the = operator) just makes a copy of the reference, but they still point to the same object. So you are, in fact, still iterating over the original HashSet.

I second BoredMormon's suggestion for LINQ, as it is awesome, but it's a slightly different paradigm.

An alternative method is to use the built-in set operators:

      HashSet<GameObject> excludedObjects = new HashSet<GameObject>();
 
      foreach (GameObject Object in myObjects)
      {
          if (Object == player) { continue; }
 
          Vector2 distance = Object.transform.position - player.transform.position;
 
          if (distance.magnitude > 5000)
          {
              Object.SetActive(false);
              excludedObjects .Add(Object);
          }
      }

      //Remove all elements in the second set from the first set.
      myObjects.ExceptWith(excludedObjects) ;
Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Wrymnn · Nov 24, 2014 at 11:11 PM 0
Share

Nice it works man thanks !! :DDDDD

No more annoying error.

avatar image Kiwasi · Nov 24, 2014 at 11:16 PM 1
Share

Note if you are going to call this code frequently or on a large collection it makes sense to use distance.sqr$$anonymous$$agnitude ins$$anonymous$$d of magnitude.

avatar image Wrymnn · Nov 25, 2014 at 07:13 AM 0
Share

Yes but I experimented all this things I learn on the internet to firstly get transform to variable not call it like transform.position or do sqr$$anonymous$$agnitude :) Tested with 400+ complex AI objects, and it did not make a slight different wether its magnitude or sqr$$anonymous$$agnitude maybe 0.1fps with 500+ AI.

avatar image Fattie · Feb 22, 2015 at 04:37 AM 0
Share

hi Wymmm uh yeah you must be using a computer made after 1970. by "large" he means millions, possibly billions.

avatar image
1

Answer by Kiwasi · Nov 24, 2014 at 10:44 PM

You can't add or remove items from a collection while using its enumerator. This is especially true of the Dictionary and HashSet collections, which have no natural order.

Couple of options to solve

  • Use LINQ to create a new collection with desired elements removed

  • Store the elements to be removed in a separate collection. Once you have all the items, iterate over the new collection to remove them from the original.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Wrymnn · Nov 24, 2014 at 10:53 PM 0
Share

But that`s what I did in my code I have showed. It didn`t work. I created new collection and iterated Over It. But it`s just throws that error even when I do it this separate way.

avatar image Kiwasi · Nov 24, 2014 at 11:01 PM 0
Share

Your code does not use a new HashSet, it modifies the original. Here is how I would code it.

 HashSet<GameObject> objectsToRemove = new HashSet<GameObject> ();
  
 foreach (GameObject Object in myObjects){
     if (Object == player) { continue; }
     Vector2 distance = Object.transform.position - player.transform.position;
     if (distance.magnitude > 5000) {
         Object.SetActive(false);
         objectsToRemove.Add(Object);
     }
 }
 foreach (GameObject object in objectsToRemove){
     myObjects.Remove(object);
 }

avatar image demented_hedgehog · Feb 22, 2015 at 03:53 AM 0
Share

I thought there was no LINQ in Unity?

avatar image
0

Answer by Cherno · Nov 24, 2014 at 10:31 PM

You can't remove elements in a foreach loop, but you can by just using a index variable like this:

 for (int i = 0; i < myObjects.size; i++)
          {
              if (myObjects[i] == player) { continue; }
  
              Vector2 distance = myObjects[i].transform.position - player.transform.position;
  
              if (distance.magnitude > 5000)
              {
                  myObjects[i].SetActive(false);
                  temporaryMyObjects .Remove(myObjects[i]);
              }
          }


Or temporarily store the current object in a variable

 for (int i = 0; i < myObjects.size; i++)
          {
              GameObject object = myObjects[i];
 
              if (object  == player) { continue; }
  
              Vector2 distance = object .transform.position - player.transform.position;
  
              if (distance.magnitude > 5000)
              {
                  object .SetActive(false);
                  temporaryMyObjects .Remove(object );
              }
          }

I have never used hashsets but it works with things like Lists, from a quick search I learned that .size get the number of elements of the hashsets so I used that as the iteration limit, dunno if it's actually the right way.

Edit: As for "modifying some other hashset", it seems like you are just referencing the original hashset with a new variable, but this will not create a new hashset, you are in fact directly accessing the original hashset, you just use the reference to access it.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Kiwasi · Nov 24, 2014 at 10:46 PM 0
Share

Note that the for approach makes no sense when using a HashSet or Dictionary. These collections have no natural index to use. You need to use for each or manually run through the enumerator with $$anonymous$$oveNext (manual manipulation is not recommended).

avatar image Wrymnn · Nov 24, 2014 at 10:51 PM 0
Share

Yes youa re right Bored$$anonymous$$ormon. The above loop won`t help since I can`t use [i] with HashSet.

That were my problem lies, I can`t iterate and remove at once.

avatar image Cherno · Nov 24, 2014 at 10:58 PM 0
Share

You could do it like this, then:

Declare a GameObject variable; this will hold the reference to the gameObject that should be removed.

In the foreach loop, once the right go is reached, just assign this one to the go variable above (and continue if you want).

After the loop is finished, just remove the stored go from your hashset.

I guess that's not what you wanted since it used additional code outside the loop, but it's a simple workaround I guess :)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

29 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Hashtable used as associative array - how to fetch element value? 2 Answers

Causing a chain reaction and hashtable errors 0 Answers

Return a Hashtable. Warning: Implicit downcast from Object to String. 0 Answers

How do I I convert a hastable to a string? 1 Answer

how to use matrice with unity 3D 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges