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 michaelto20 · Apr 30, 2015 at 05:55 AM · gameobjectlistrandomlinqrandomly

How to randomly iterate through a list of objects without repeating?

Note: this is a classic general programming problem and nothing to do with Unity.

You simply SHUFFLE a list to achieve this.

(To shuffle in unity, just do something like this,

return ints.OrderBy(Rx => Random.value).ToArray();

it's a basic, you do it many times in any game, all over the place.)


I have a list with GameObjects as elements. How can I randomly select each one but never select the same one twice?

Comment
Add comment · Show 2
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 Rotary-Heart · Apr 30, 2015 at 06:56 AM 0
Share

Are you running this code on update function? It's not giving you only a nomber, its giving you the random position. Just use that position to get the object from your list.

avatar image michaelto20 · May 03, 2015 at 07:41 PM 0
Share

I wasn't running it in the update function but ins$$anonymous$$d, it is in a method that is called when the mouse clicks on a certain object. I see what you are saying about it returning the index number in the list. I should've realized that but my brain was too tired from spending hours on this project. Thanks for your thoughts.

3 Replies

· Add your reply
  • Sort: 
avatar image
3

Answer by steakpinball · Apr 30, 2015 at 02:06 PM

The other answers here provide solutions with indeterminate runtime. At best they will run fine, at worst they will take an infinite amount of time. A common practice for randomizing order is to shuffle the original order.

 void ShuffleArray<T>(T[] array)
 {
   int n = array.Length;
   for (int i = 0; i < n; i++) {
     // Pick a new index higher than current for each item in the array
     int r = i + Random.Range(0, n - i);
     
     // Swap item into new spot
     T t = array[r];
     array[r] = array[i];
     array[i] = t;
   }
 }
 
 // Somewhere else
 // objectList is a List<GameObject>
 
 // We don't want to mess up the original list, copy it
 var objectArray = objectList.ToArray();
 ShuffleArray(objectArray);  // Call this more to shuffle again
 foreach (var o in objectArray) {
   // This will be a random order of objectList
 }
 

This shuffle algorithm is known as the Fisher-Yates Shuffle. It has a runtime of O(n), meaning the time it takes scales with the size of the list.

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 michaelto20 · May 03, 2015 at 07:36 PM 0
Share

That's awesome, thanks! I love learning new algorithms and seeing the logic behind them. Thanks for sharing your smarts.

avatar image Fattie · May 15, 2015 at 05:05 PM 0
Share

However $$anonymous$$ichael, Don't write your own shuffle - no more than you'd write your own List handling.

avatar image christianblevensbarb · Sep 09, 2021 at 06:51 AM 0
Share

int r = i + Random.Range(0, n - i);

int r = i + Random.Range(-i, n - i); Is better. Provides an even distribution while Random.Range(0, n - i) is biased to larger numbers.
avatar image
-1

Answer by Addyarb · May 03, 2015 at 08:17 PM

My solution would be something a little more simple/approachable than most here. This won't be as "Random" as the others mind you, but the player won't know it anyway either way, right?

     int CurrentID;
     public GameObject[] myArray;
     GameObject mySelectedGameObject;
 
     void Start(){
         InvokeRepeating ("SelectRandom", 0, 1);
     }
     void SelectRandom(){
         int lastID = CurrentID;
         int randomInt = Random.Range (0, myArray.Length);
         if (randomInt != lastID) {
             mySelectedGameObject = myArray [randomInt];
             CurrentID = randomInt;
         } else {
             if (lastID !=  myArray.Length-1) {
                 mySelectedGameObject = myArray [++lastID];
                 CurrentID = lastID + randomInt;
             }
             else{
                 mySelectedGameObject = myArray [--lastID];
                 CurrentID = lastID + randomInt;
             }
         }
     }

Comment
Add comment · 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
0

Answer by CalxDesign · Apr 30, 2015 at 07:18 AM

I'd steer clear of Linq where possible, especially if what you're doing is performance critical. Try keeping a list of objects you've already selected in that sequence, then check that list for your next selected object. Something like this funciton should do the trick, but you may wish to add some more robust safety checks to avoid infinite loops etc - This is untested.

 private List<GameObject> UniqueSelected(List<GameObject> gameObjects, int targetNumber) 
 {
     List<GameObject> selected = new List<GameObject>();
 
     while (selected.Count < targetNumber)
     {
         GameObject go = gameObjects[(int) Random.Value * gameObjects.Count];
 
         if(!selected.Contains(go)) 
         {
             selected.Add();
         }    
     }
 
     return selected;
 }

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 michaelto20 · May 03, 2015 at 07:39 PM 0
Share

Thanks for the heads up about Linq. I'm only in CS1301 and we haven't learned anything about them. Also thanks for your input about how to randomize a list. I went ahead and used Linq after my professor helped show me how to make it work in my project.

avatar image Fattie · May 15, 2015 at 05:00 PM 0
Share

You should always use Linq at all times. Never, ever consider performance -- except in the exceedingly rare cases where you have to.

Just TBC it's inconceivable this is something that would be happening every frame, or even often. It wouldn't matter, at all, how long it takes. Yo'd no more optimise this than you'd worry about using a raw array somewhere, rather than a "string".

avatar image CalxDesign · May 15, 2015 at 05:13 PM 1
Share

See how far that advice gets you with iOS.

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

9 People are following this question.

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

Related Questions

A node in a childnode? 1 Answer

Reset Generic List To Empty(C#, Urgent!) 2 Answers

Instantiate random from a list gives error: "Reference not set to an instance" 1 Answer

Can't add GameObjects to ArrayList 1 Answer

Keep adding targets to a list 2 Answers


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