Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Randomisation script.

Discussion in 'Scripting' started by BigDreamsPoorReality, Mar 3, 2016.

  1. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14
    Hello, I'm a beginner at scripting in C# and asking for some guidence on a script i'm willing to work on.

    I want to script something that randomly chooses 1 out of of 2 gameobjects as the "correct" one. Lets say I have 2 buttons. I want the script to make one of the 2 buttons the correct one. So if I happen to press the correct one I proceed, and hitting the other one will make me lose.

    Would it be hard to script such behaviour? ( I wouldn't think so)
    And if you're able to post a script i'd be glad to know how it works so I can learn from it, since that's what i'm here for... :)
     
  2. SneeKeeFahk

    SneeKeeFahk

    Joined:
    Jan 25, 2015
    Posts:
    26
    Code (CSharp):
    1. // declare this as static and global in the class
    2. Random rnd = new Random();
    3.  
    4. // us this to randomly select a gameobject in the array of gameobjects you want to chose from
    5. var correct = myObjs[rnd.Next(0, myObjs.Length)]
    this assumes you objects are in an array of gameobject called myObjs
     
    BigDreamsPoorReality likes this.
  3. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14
    Thanks! Mind explaining for a newbie what they do/mean? :3
     
  4. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14
    More answers are welcome!
     
  5. Craze74

    Craze74

    Joined:
    Nov 19, 2012
    Posts:
    83
    Random rnd is the part where the random function is called, each time this will be called it will return a random number, depending what parameter you entered.

    In this example :
    Code (CSharp):
    1. var correct = myObjs[rnd.Next(0, myObjs.Length)]
    you are calling a random number between 0, and "myObjs.Length", which means the total objects you have in your myObjs list.
    It will result getting a total random number between 0 and 9 for example if you have 10 objects to list
     
    BigDreamsPoorReality likes this.
  6. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14
    Thank you for the explanation! Just one question. How would I add my objects into myObjs list, where do I do that? ;o
     
  7. Craze74

    Craze74

    Joined:
    Nov 19, 2012
    Posts:
    83
    I will let someone answer to that since this is something I never had to do yet :)
    Basicly I imagine that at the beginning of your script you are just putting in a list / array all the gameobjects you want

    In algorythm it will looks like something like :
    Code (CSharp):
    1.  
    2. myObjs = [ "object1", "object2", "object3"];
    that way if you say :
    Code (CSharp):
    1. var correct = myObjs[rnd.Next(0, myObjs.Length)]
    each time the variable "correct" will return you a value between 0 and 2, 0 being your first index [0] of your list, so your first element "object1".


    I will still let somebody who actually knows how to translate that correctly in js for unity :)
     
    BigDreamsPoorReality likes this.
  8. SneeKeeFahk

    SneeKeeFahk

    Joined:
    Jan 25, 2015
    Posts:
    26
    I've thrown together a quick extension method and example of how to use it.

    first, define the extension method. To avoid the issues with Random and how its not so random when you create a new one every time, I added the Random object as a static instance in Extensions class. This also uses generics which is kind of out of scope for this question but suffice to say we need this to make this handle any object you want to randomly select. Just throw this code into its own code file anywhere in the project:
    Code (CSharp):
    1. public static class Extensions{
    2.    
    3.     // this creates a static instance using the current millisecond as the seed
    4.     private static Random myRandom = new Random(DateTime.Now.Millisecond);
    5.    
    6.     ///
    7.     public static T GetRandomItem<T>(this System.Collections.Generic.IList<T> list){
    8.         return (T)list[myRandom.Next(0, list.Count)];
    9.        
    10.     }
    11. }
    here is an implementation, i created a simple structure called obj that just has a name property, then i add a bunch of those to a generic list and call the extension method to pull out a random one:

    Code (CSharp):
    1.     public struct obj {
    2.         public string name;
    3.     }
    4.    
    5.     public void Main(){
    6.  
    7.         var lst = new System.Collections.Generic.List<obj>();
    8.         lst.Add(new obj { name = "test 1" });
    9.         lst.Add(new obj { name = "test 2" });
    10.         lst.Add(new obj { name = "test 3" });
    11.        
    12.         Console.WriteLine(lst.Count);
    13.         for(int i = 0; i <= 100; i++)
    14.             Console.WriteLine(lst.GetRandomItem<obj>().name);
    15.     }
     
    BigDreamsPoorReality likes this.
  9. Craze74

    Craze74

    Joined:
    Nov 19, 2012
    Posts:
    83

    Hi !

    Thanks for your exemple, however I am having troubles seeing what you are doing here exactly, I am relatively new to creating my own class, what exactly is T ? On what is this different from just putting the line "list[myRandom.Next(0, list.Count)]" each time we need it ?

    Cheers
     
  10. SneeKeeFahk

    SneeKeeFahk

    Joined:
    Jan 25, 2015
    Posts:
    26
    Hey Craze,

    T is how we define it as generic, you can read up on that here, but basically it allows you to dynamically define the type at runtime. So basically what this is saying is:

    public static T GetRandomItem<T>(this System.Collections.Generic.IList<T> list)

    create a public static method (static so you don't need an instance to use the function) which can will return an object of T from a list of T. You define what T is when you call the function. So in this example we created a Generic method that will operate on a list of any type of object and return the specified type. We specify the type when we call the function.

    So if you wanted to get a random Integer from a list of integers this function would allow you to do that like this:

    var myList = new List<int>(); // here we create a new generic list of ints
    myList.add(1); // because we defined this list of T as integers the add function now only accepts integers
    myList.add(2); // just add another one

    // now we want to get an int from that list
    int myRandom = myList.GetRandomItem<int>(); // here we tell the GetRandomFunction that its T parameter is int so it knows it is operating on a list of integers and it needs to return an integer.

    using <int> effectively turns this code:
    public static T GetRandomItem<T>

    into this code
    public static int GetRandomItem(IList<int> list)

    I hope this makes sense but if it doesn't don't hesitate to ask follow up questions.
     
  11. SneeKeeFahk

    SneeKeeFahk

    Joined:
    Jan 25, 2015
    Posts:
    26
    To speak to this point, there is nothing wrong with that but you end up writing the same code all over the place that does the exact same thing. By moving that code into a generic extension method, you write the code once and reference it everywhere else, kind of like the idea behind components in unity. You can read up on extension methods here.
     
  12. Craze74

    Craze74

    Joined:
    Nov 19, 2012
    Posts:
    83
    Thanks a lot for this explanation, this will be really helpful !!

    Cheers !
     
  13. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14
    Thanks for the help!
     
  14. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14


    public class Probability : MonoBehaviour {
    public class GameObject


    // Use this for initialization
    void Start () {

    Random rnd = Random();

    var correct = Buttons[rnd.Next(0, Buttons.Lenght)];

    }

    // Update is called once per frame
    void Update () {

    if ("pressed correct proceed to next level...)

    }
    }


    Okay! So as my first attempt of creating this script it didn't quite seem to work (errors) as expected.
    But i'll go ahead and tell how I tried to set it all up in hope for corrections!

    First: Public class GameObject. I tried to refer GameObject as my 2 buttons.
    Second: Make the script chose one of the 2 buttons as the correct one (under void Start.)
    Thirdly:
    If correct button is pressed, then proceed to next lvl/scene. (I already have a script on changing scene/next lvl.)

    I've made all the material necessary for this game so the scripting is the only thing left and i'm finding it really hard to learn from tutorials and then adapt it to my own wanted script.

    If you don't mind answering, how did you learn C#, was it tough in the beginning or...?
     
  15. SneeKeeFahk

    SneeKeeFahk

    Joined:
    Jan 25, 2015
    Posts:
    26
    Hey BigDreams,

    I've been programming in C# for over 10 years and its what I do for a living. I actually went to school to learn it but learning programming is difficult but once you grasp some of the basic concepts it gets much easier. Don't give up, if it was easy to learn everyone would do it.

    Now to your problems, there are a couple but dont take them as an attack at your attempt rather some constructive feedback to help you out.

    First it looks like you are confused over classes and its giving you your first issue in the code. Classes (or objects as they are often refereed to) are the basis for Object Oriented Programming. At first it seems like a hard thing to understand and starting with Unity kind of throws you right into some of the more complex things to understand like polymorphism and inheritance. These are very simple concepts to grasp though, you don't need to fully understand the implementation and all that other confusing stuff about and just remember this,

    Lets say you create an object, lets call it Base because it will be a base class but we will get into that in a minute. In Base you create a bunch of common functionality like Name, Age, HairColour properties and a Birthday function that adds 1 to their age. Now lets say you want to create a Boy and a Girl object both of which will have Name, Age, HairColour and a Birthday function. Instead of writing that code inside the Boy and Girl classes you can simply inherit from Base and those properties will now be available on both the Boy and Girl classes. This is inheritance and there is no limit to how deep you can go. In C# you can only inherit from 1 class but that class can inherit from another class and so on until your hearts content. You specify the base class but putting : Base after the definition of your class. Here is an example of the code we just talked about.

    Code (CSharp):
    1.     class Base{
    2.         public string Name;
    3.         public int Age;
    4.         public string HairColour;
    5.        
    6.         public void Birthday(){
    7.             Age += 1;
    8.         }
    9.     }
    10.    
    11.     class Boy : Base {
    12.        
    13.     }
    14.    
    15.     class Girl : Base{
    16.        
    17.     }
    both Boy and Girl now have the same properties and functions as Base even though we didnt have to define them. This is why all your GameObjects in Unity inherit from MonoBehaviour because they need to have the basic functions for Unity to be able to call the default functions such as Start, OnEnable and so on. This leads into the topic of polymorphism. Even the word is scary but it's super easy to understand. Polymorphism basically means that we can cast both Boy and Girl as Base because they inherit from it. Unity uses this to actually call the functions on your game objects without actually knowing about the implementation of the functions, it just casts your object down to MonoBehaviour and calls the functions it knows are then.

    Now that you understand that we can look at the first 3 lines of your code.

    Code (CSharp):
    1.     // Here you are defining a class that inherits from MonoBehaviour
    2.     // which is exactly what you want for your Probability object to
    3.     // be able to belong to a GameObject (not the one you defined but
    4.     // an acutal GameObject inside Unity.
    5.     public class Probability : MonoBehaviour {
    6.     // this is where you start getting confused, becuase you nested this
    7.     // class inside of Probablity without implementing any code inside of
    8.     // probablity. Probablity has no properties or functions and is simply
    9.     // a container for GameObject. There is no need for this, you should
    10.     // create these in different files. Another issue with this code is
    11.     // your class is called GameObject. Dont do this. There is already a
    12.     // GameObject inside of Unity and you are going to create headaches
    13.     // for yourself later when you start messing with Namespaces. Just
    14.     // call it MyGameObject or something else but make it descriptive
    15.     // there is no limit to the length of a class name so make it easy to
    16.     // understand
    17.     public class GameObject
    18.        
    19.     // this should look like this:
    20.     public class Probability : MonoBehaviour {
    21.     }
    22.        
    23.     public class MyGameObject : MonoBehaviour {
    24.     }
    The next thing you are confused with is Scope. Scope is not too hard to understand. To explain scope a little better, here is a code snippet with comments.

    Code (CSharp):
    1.     // this class is public, that means everything can access it
    2.     // its in the 'public' scope
    3.     public class ScopeExample
    4.     {
    5.         // this is private, this value cant be accessed outside of
    6.         // this class but anything inside this class can access it
    7.         private int myVal = 1;
    8.  
    9.         // you probably wont use Internal but it just means
    10.         // only objects in this project can call this method
    11.         // so if Boy created a ScopeExample object it would be
    12.         // able to call it but if someone took your DLL and
    13.         // used it they wouldnt be able to call Print
    14.         internal void Print(string val){
    15.             Console.WriteLine(val);
    16.         }
    17.        
    18.         // This is public again so anything that creates
    19.         // a ScopeExample can call SayHello
    20.         public void SayHello(){
    21.             // here we can access the private myVal
    22.             // variable because SayHello is inside
    23.             // ScopeExample.
    24.             myVal += 1;
    25.             // here we call the Internal Print function
    26.             Print("Hello");
    27.         }
    28.        
    29.         // This is public again so anything that creates
    30.         // a ScopeExample can call HowManyTimesHaveISaidHello
    31.         public void HowManyTimesHaveISaidHello(){
    32.             // this is it's own scope. and ScopeExample can't see this variable
    33.             // and no other function here can access it. It is also destroyed
    34.             // when this function is finished executing because it is now
    35.             // out of Scope
    36.             string myString = "You've said Hello " + myVal + " times.";
    37.             // call the internal Print method
    38.             Print(myString);
    39.            
    40.             // myString is destroyed after this
    41.         }
    42.     }
    43.    
    So your second problem is your GameObject doesnt have a Buttons property, the Scope of correct is in Start (it should be in GameObject)


    Now your third question. Now that you have stored correct in the right Scope (inside GameObject) you want to check if that is what the user clicked inside your click event of the buttons you added to GameObject. If it is call your existing code to change the level.
     
    BigDreamsPoorReality likes this.
  16. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14

    Wow such generosity. Thank you very much! I will work on it and try n understand as best as possible.
     
  17. SneeKeeFahk

    SneeKeeFahk

    Joined:
    Jan 25, 2015
    Posts:
    26
    BigDreamsPoorReality likes this.
  18. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14
    Code (CSharp):
    1. public class Random : MonoBehaviour {
    2.     public class Buttons : MonoBehaviour {
    3.  
    4.         Random rnd = new Random();
    5.  
    6.     }
    7.     public class ChangeScene : MonoBehaviour
    8.     {
    9.  
    10.         public void ChangeToScene(int sceneToChangeTo)
    11.         {
    12.  
    13.             Application.LoadLevel(sceneToChangeTo);
    14.             {
    15.  
    16.  
    17.             }
    18.  
    19.  
    20.         }
    21.         // Use this for initialization
    22.         void Start() {
    23.             var correct = Buttons[rnd.Next(0, Buttons.Length)]; // It says Random.Buttons do not contain a definition for 'Lenght'.
    24.  
    25.         }
    26.  
    27.         // Update is called once per frame
    28.         void Update() {
    29.  
    30.             if (Input.GetTouch) = correct(ChangeToScene); //Change to next level.
    31.  
    32.             else if (Input.GetTouch) = !correct //Show Game over screen.
    33.  
    34.      
    35.                     }
    36.        
    37.            }
    38.  
    39.   }
    So I think i've gotten some of it right. I think I need to practice the commands though. Like "if input.gettouch = correct(ChangeToScene)" seems really wrong, haha.

    So with the Public Class ChangeToScene I guess I made a public Scope out of public void ChangeToScene that I later used in void update?

    At first I am trying to regenerate 1 out of the buttons as 'correct'. Then I am trying to use the term 'correct' to clarify what happens if it is pressed. If it is pressed, then I tried to make it change scene. But then I thought I need a command for "If the other button is pressed, then show gameover." Maybe something like if(input.gettouch) = !correct(refering to other button) then show GO-screen.

    Any thoughts?


    Sorry I don't know how to make it in a code tag. Nevermind.
     

    Attached Files:

    Last edited: Mar 5, 2016
  19. SneeKeeFahk

    SneeKeeFahk

    Joined:
    Jan 25, 2015
    Posts:
    26
    Hey BigDreams,

    Don't take this the wrong way but there is a lot you need to learn about programming and I commend you for starting down this road, don't let your first stumble dissuade you. If you are going to be creating things with Unity you are going to first have to learn how to code. There are a ton of really great resources out there and Microsoft has a ton of free software and learning resources to get you going. Remember you don't need to be a pro to make games in Unity but you need to have a firm understanding of the how programs work and how the code is structured.

    Having said that; I cleaned up your code for you so you can see what it should look like but it wont do what you are wanting it to do.

    Code (CSharp):
    1. /// <summary>
    2. /// You only need one class
    3. /// </summary>
    4. public class MyFirstClass : MonoBehaviour
    5. {
    6.     /*  declare these variables inside the class */
    7.  
    8.     /// <summary>
    9.     /// Your random number generator, its private because only this needs to use it
    10.     /// </summary>
    11.     Random rnd = new Random();
    12.  
    13.     /// <summary>
    14.     /// The collection of your buttons, its public so it can be set
    15.     /// </summary>
    16.     public System.Collections.Generic.List<GameObject> Buttons;
    17.  
    18.     /// <summary>
    19.     /// The "Correct" button to press, private because only this needs to use it
    20.     /// </summary>
    21.     GameObject correct;
    22.  
    23.     // declare your functions inside the class
    24.     public void ChangeToScene(int sceneToChangeTo)
    25.     {
    26.         Application.LoadLevel(sceneToChangeTo);
    27.     }
    28.  
    29.     void Start()
    30.     {
    31.         correct = Buttons[rnd.Next(0, Buttons.Count)];
    32.     }
    33.  
    34.     void Update()
    35.     {
    36.         // this code will not work but its what your code should look like
    37.         if (Input.GetTouch == correct)
    38.         {
    39.             ChangeToScene(1);
    40.         } else{
    41.             // Show Game Over screen.
    42.         }
    43.     }
    44. }

    If you really want to jump right into Unity, which is fine and your choice, I would recommend you start at the very first video here (by first i mean oldest) http://unity3d.com/learn/live-training. Mike Geig does a great job of explaining whats happening, why you should do it and even explains some of the basics of programming.

    Please don't let this get you down and do continue learning how to both code and build games, it's much easier than it seems and is a lot of fun. Don't hesitate to ask any follow up questions you have either.
     
  20. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14
    Hello SneeKee.

    I'm starting to learn JS in about 5 months at school so maybe I should go with Unity for now. :)
    I am very thankful for all the time you have spent on helping me and I couldn't be happier!
    Thank you once again for the amazing feedback and i'm lucky I met you on my road.

    Best wishes, BigDreams.
     
  21. BigDreamsPoorReality

    BigDreamsPoorReality

    Joined:
    Jan 1, 2016
    Posts:
    14
    I made a new thread on a different topic/idea. if anyone wanna sneak by.