Search Unity

Random string Percentage/Chance?

Discussion in 'Scripting' started by batistaa65, Oct 16, 2017.

  1. batistaa65

    batistaa65

    Joined:
    Jul 17, 2014
    Posts:
    56
    i have a string[] of (my game is for fishing) fish. Common, Grass, and Buffalo. i know how to get a random string from the array, but i don't know how to set each type of fish to be based of percentages. say common is 60% likely to get caught, grass has 30%, and buffalo has 10%. how would i do this with a string array instead of an int array?
     
  2. batistaa65

    batistaa65

    Joined:
    Jul 17, 2014
    Posts:
    56
    this is my script so far:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;

    public class TestMyKnowlege : MonoBehaviour {



    public string[] typeoffish;
    public string fish;
    int scalesDOT;
    int DOTscales;
    public Text BeforeDot;
    public Text AfterDot;
    public Text fishText;


    void Start(){


    fish = typeoffish [Random.Range (0, typeoffish.Length)];
    DOTscales = Random.Range (1, 9);
    scalesDOT = Random.Range (5, 20);
    BeforeDot.text = scalesDOT.ToString();
    AfterDot.text = DOTscales.ToString();
    fishText.text = fish;

    //prints the elements of the array and string of same name
    //in the console.

    print (scalesDOT);
    print (DOTscales);
    print (fish);
    }

    void Update(){

    }


    }
     
  3. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
  5. batistaa65

    batistaa65

    Joined:
    Jul 17, 2014
    Posts:
    56
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class TestMyKnowlege : MonoBehaviour {
    7.  
    8.  
    9.  
    10.     public string[] typeoffish;
    11.     public string fish;
    12.     int scalesDOT;
    13.     int DOTscales;
    14.     public Text BeforeDot;
    15.     public Text AfterDot;
    16.     public Text fishText;
    17.  
    18.  
    19.     void Start(){
    20.        
    21.  
    22.         fish = typeoffish [Random.Range (0, typeoffish.Length)];
    23.         DOTscales = Random.Range (1, 9);
    24.         scalesDOT = Random.Range (5, 20);
    25.         BeforeDot.text = scalesDOT.ToString();
    26.         AfterDot.text = DOTscales.ToString();
    27.         fishText.text = fish;
    28.  
    29.         //prints the elements of the array and string of same name
    30.         //in the console.
    31.  
    32.         print (scalesDOT);
    33.         print (DOTscales);
    34.         print (fish);
    35.     }
    36.  
    37.     void Update(){
    38.        
    39.     }
    40.  
    41.  
    42. }
     
  6. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Easiest way would be to put the elements in the array according to their probability. Fe in an array of size 10 have 6 times a certain fish for 60%. There are more advanced aproaches. If you want to spend money have a look at MakeItRandom at the AssetStore.
     
  7. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I believe the link from @Brathnann covered it nicely :)
     
  8. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    Since the numbers are devisable by 10, you only need one random range of 10. If it's 1, it's the 10 percent, if it's 2 to 4, it's the 30 percent, if it's anything above, it's the 60 percent.

    Also, his description of it having to add up to 100 percent is silly. If you want 10 percent, choose one number. If you want 50 percent, choose 5 numbers. if you want 90 percent choose 9 numbers of a given roll.
     
    Last edited: Oct 20, 2017
  9. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Why would you choose 5 numbers, 9 numbers? What? You roll once. You only get one number. Your definition doesn't make sense to me.

    The percent is the chance to get a number. Not the amount of numbers to pick.

    1 - 20%
    2 - 30%
    3 - 50%

    So that's 100%. If I roll a 20% or less, my number is 1. If I roll 21-50%, my number is 2. If I roll 51%-100%, my number is 3. That's all it is to it.

    He used percent because it was easier to explain it. You could just as easy do 1-10 or 0 - 1f.
     
  10. batistaa65

    batistaa65

    Joined:
    Jul 17, 2014
    Posts:
    56
    By the way, I'm more than likely to have more than 10 types of fish. So would I use 1-11 if I have 11 fish? How would that translate to a float?
     
  11. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    Yes, but how do you get a 20 percent chance of random numbers? You take a range of 10, and pick 2 of those numbers as the correct answer for the 20 percent chance. If I get 2 numbers out of 10, that's a 20 percent chance. It's still off one random range number. It's just a grouping from 10 numbers that gives the odds. He did much the same thing in your link, I think. I did just glance at it, though. You are only getting one number, it's just what range it falls in.
     
    Last edited: Oct 20, 2017
  12. batistaa65

    batistaa65

    Joined:
    Jul 17, 2014
    Posts:
    56
    Omg I'm an idiot. I see what you are saying now. No matter how many types of fish I have, all the percentages will add up to 100%. So 1-10 will work no matter what.
     
  13. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    What I do with weighted randoms is sum up the weights, perform a Random.Range, and then iterate the droplist subtracting the chance till the result is less than 0. Once it does I found my drop.

    Code (CSharp):
    1.  
    2. float dropRateSum = 0f;
    3.  
    4. for(int i=0;i<drops.Length;i++)
    5. {
    6.     var drop = drops[i];
    7.  
    8.     dropRateSum += drop.dropRate;
    9. }
    10.  
    11. float dropChance = Random.Range(0,dropRateSum);
    12.  
    13. for(int i=0;i<drops.Length;i++)
    14. {
    15.     var drop = drops[i];
    16.  
    17.     dropChance    -= drop.dropRate;
    18.  
    19.     if(dropChance    <0f) return drop;
    20.  
    21. }
    22.  
    23. return null;
    24.  
    This way the drop rates can be any value, they don't have to add up to 100%
     
  14. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Let's say it slightly different:
    You don't have to choose values that add up to 100.

    Looking at it from a math-perspective, the accumulated value which you call dropRateSum is still 100%.:p

    I'd only calculate the sum once in the beginning though, unless it's meant to add / remove certain drops now and then. Then I'd calculate it whenever the drop list changes.
     
  15. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    You right, its still 100%-based, I like it however as its far less error prone. You can then think in terms of "I want drop A to be 3 times more likely than drop B" yet not worry about having it add up to something.

    If you actually had a droptable class then you could cache the dropRateSum, calculating it when the class is considered dirty. and yes, the class would be dirtied on construction, or when you add/remove a drop (in which case should be a struct).

    however I wouldn't worry too much about caching the sum. Performance-wise, the algorithm will still be Big O (n), with or without that extra for loop. Plus if the drop is not a struct (and if you assume the drop table is always dirty) then its safe for the drops own weight to be altered at runtime. For example, using a certain type of bait that makes a certain fish twice as likely to be caught.
     
  16. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Yes, I understand. And there's nothing wrong about it, I'd so it similarly. In the end though, you still might want to have the useful representation in percentage. So "normalization" could be handy to get a better overview of the actual probability.

    True, for a small set of items that's not significant. Once it grows larger, say hundreds or thousands of items, it'll be more of a concern. And those might also be dropped at once (think of [MMO]RPGs). But ye, that's a whole different story.
     
  17. jl2l

    jl2l

    Joined:
    Nov 30, 2016
    Posts:
    2
    for anyone wanting a oneliner

    this will catch the fishXYZ "75%" of the time,

    Code (CSharp):
    1. bool[] fishXYZ = { false, true, true, true }; // adjust for the % eg
    2.  
    3.   IsCaught = fishXYZ[Random.Range(0, fishXYZ.Length)];