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

Randomising/shuffling library

Discussion in 'Scripting' started by andeeeee, Sep 8, 2009.

  1. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Questions about generating random orderings and choices crop up quite often, so I've put together a library of routines for common randomising tasks. The main functions are for randomly shuffling an array, picking items randomly but with different probabilities, and "choosing without replacement", ie, picking some items from a list without ever getting the same one twice. Follow up this post if you have any questions or suggestions.

    To Chaos!

    PS - I found a bug in the SampleRemove function which is now fixed and uploaded as of 8 July 2010.
     

    Attached Files:

    Orrib and Ali_V_Quest like this.
  2. jmunozar

    jmunozar

    Joined:
    Jun 23, 2008
    Posts:
    1,091
    Wow, awesome!

    Thanks, I was thinking in something like this yesterday for a demo I'm making

    really thanks!, will give it a try :D
     
  3. bedalowe

    bedalowe

    Joined:
    Sep 27, 2009
    Posts:
    22
    Awesomeness! This is great. Thanks Andeeeeeeeeeeee!
     
  4. bedalowe

    bedalowe

    Joined:
    Sep 27, 2009
    Posts:
    22
    One question. Is this in C+?
     
  5. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    It is indeed C#.
     
  6. bedalowe

    bedalowe

    Joined:
    Sep 27, 2009
    Posts:
    22
    Hmmm. I'm using JS...Will it be easy for a complete novice to convert the ideas to js do you think? :)
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You don't really need to convert them. It doesn't matter what language this library is written in; the functions are static, so just put the script somewhere like Standard Assets scripts (this way it won't need to be recompiled with your normal scripts), and call the functions as normal.

    --Eric
     
  8. Hanankk

    Hanankk

    Joined:
    Sep 2, 2008
    Posts:
    103
    so Andeee, how can i access the SampleRemove function from javascript??
    i tried several time but i couldn't,
    could u plz just write a small example for the javascript writers??
    :oops:
     
  9. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Firstly, place the Randomness.cs file in your Standard Assets folder to ensure it gets compiled before any JS file. Then, you can call the SampleRemove function like any other function:-
    Code (csharp):
    1. var rangeTop = 10;
    2. var numSamples = 5;
    3. var nums: int[] = RandFuncs.SampleRemove(rangeTop, numSamples);
    The first parameter is the upper end of the range of numbers. This works like Random.Range, so the numbers go from 0 to rangeTop - 1, which is useful for array indices. The second parameter is the number of samples you want from that range. The same sample isn't chosen twice, so the number of samples can't be larger than the range. It's worth noting that the samples will be returned in numerical order - if you want them scrambled, use the Shuffle function on the array afterwards.

    Also, I should apologise: I discovered a bug in SampleRemove on looking at it again :oops: I've fixed it now and replaced the old version of the file.
     
  10. Creative

    Creative

    Joined:
    May 8, 2010
    Posts:
    184
    Thank you andeee.
    I'm going to take a look.
     
  11. we rock

    we rock

    Joined:
    Jul 31, 2009
    Posts:
    15
    @andeeee:

    I've started with an empty project from scratch (with no standard assets folder) and now i'm confused where should i put this script, to get it compiled first...

    Also i receive a warning message which says "Couldn't load the script "Randomness" because its file name doesn't match the class name.
    Please make sure the file name of the script is the same as the class defined inside it.
    "
    am i supposed to modify this Randomness.cs script or should i use it just the way it is?


    Thanks a lot
     
  12. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    We all now know why andeeeeee is so awesome. He's living in the future!
     
  13. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    Create an new folder named Standard Assets and put the script in there :p.

    The warning message was probably a result of trying to add the script to the scene. If it is just used for its static functions, it should not be necessary to place it in the scene.

    On a compltly unrlatd not: plas appricat th ffort going into this post, considring my ky brok.
     
    Ali_V_Quest likes this.
  14. we rock

    we rock

    Joined:
    Jul 31, 2009
    Posts:
    15
    Update:

    I've renamed Randomness to RandFuncs and also added " : MonoBehaviour " to the public class. i put this RandFuncs script beside my js scripts and called it by:

    Code (csharp):
    1. function Start()
    2.     {
    3.         var nums: int[] = GetComponent("RandFuncs").SampleRemove(howManyQuestion, howManyQuestionPick);
    4.         print(nums);
    5.     }
    and i get the following error:

    System.Int32[]
    UnityEngine.Debug:Log(Object)
    UnityEngine.MonoBehaviour:print(Object) (at C:\builds\unity-trunk\unity\Runtime\Export\Generated\BaseClass.cs:799)
    textLoader:Start() (at Assets\Scripts\question\textLoader.js:88)

    any advice is highly appreciated.
     
  15. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    Possibly a stupid question, but did you add the script component to your GameObject?
     
  16. we rock

    we rock

    Joined:
    Jul 31, 2009
    Posts:
    15
    yes, i also tested it as a component. the same result... system.int32[]......
     
  17. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    Wait, this is happening on the print call? If you comment out the print, does it still error out?

    Also check if the GetComponent("RandFuncs") is null (not sure if that's what you said you tested). And is that the error message? It looks more like just a stack trace. Also try printing a property of the Int32[] array rather than the array itself (such as length, the value at index 0, etc.)
     
  18. we rock

    we rock

    Joined:
    Jul 31, 2009
    Posts:
    15
    @ FizixMan:

    I really appreciate your help. i managed to solve the mystery by defining the array with "var nums : Array;"... all done. :p
     
  19. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    See, Max Headroom was only 20 minutes in the future but I'm two days ;-)

    Just to recap: you don't need to attach the Randomness script to any object, in fact you won't be able to do that with the script as it is. Just place it in the Standard Assets folder (this is just to make it available to JS code). All functions in that class are static, so you can call them from anywhere without referring to any object.
     
  20. Anim

    Anim

    Joined:
    Aug 11, 2008
    Posts:
    289
    I have been looking for a way to shuffle an array of 3 ints but cant seem to get it to work in JS. Can anybody please post an example?
     
    Last edited: Oct 29, 2010
  21. groovfruit

    groovfruit

    Joined:
    Apr 26, 2010
    Posts:
    257
    Andee -- hope you're still reading this post.

    I'm having trouble using the RandFuncs.SampleRemove function. If i call var nums : int[] = RandFuncs.SampleRemove etc etc... how do I use this in relation to finding a random number/object within my range? Do I do Random.Range first and use that somehow with SampleRemove?? I also want to shuffle my range.

    Ech all this random stuff is doing my head in atm >< **

    Big thanks
     
  22. KodaL

    KodaL

    Joined:
    Apr 4, 2008
    Posts:
    37
    Just found this and it is awesome! Think it will work perfectly for what I need. This should be stickied or something. Took me a long time to find it.

    Thanks Andeeee!
     
  23. tex1820

    tex1820

    Joined:
    Apr 6, 2011
    Posts:
    6
    Hi Everyone,

    This is my first time trying to use a class like this. I put the script into the Standard Assets folder and tried using the Shuffle function:

    questionArray = GetComponent("RandFuncs").Shuffle(questionArray);

    I am getting a Null Reference Exception. Could someone tell me what I am doing wrong?

    Thanks!
     
  24. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    You don't need to use GetComponent since the functions are static. If the script is in Standard Assets then you just need to refer to the class name when you call a function:-
    Code (csharp):
    1. RandFuncs.Shuffle(questionArray);
     
  25. fffMalzbier

    fffMalzbier

    Joined:
    Jun 14, 2011
    Posts:
    3,276
    Thanks for sharing!
    Randomize stuff is not easy (had to do it myself), so I'm glad someone is sharing stuff like this.
     
  26. seldom

    seldom

    Joined:
    Dec 4, 2013
    Posts:
    118
    There is a problem with the shuffle algorithm used in this library. Even though it does consider all possible permutations, some of them occur more frequently than others. This article explains it in detail.

    This modified version returns all permutations with equal frequency:
    Code (csharp):
    1.  
    2.     // fisher yates shuffle
    3.     static void Shuffle<T>(T[] array)
    4.     {
    5.         T tmp;
    6.         int swapIndex;
    7.  
    8.         for (int i = array.Length - 1; i > 0; i--)
    9.         {
    10.             // Swap element "i" with a random earlier element or itself
    11.             swapIndex = Random.Range(0, i+1);
    12.             tmp = array[i];
    13.             array[i] = array[swapIndex];
    14.             array[swapIndex] = tmp;
    15.         }
    16.     }
    17.  
    I know the thread is old, but it's referenced by the scripting FAQ and I just stumbled upon it. So there.
     
    S_Darkwell likes this.