My code has some invalid arguments
My code has some invalid arguments. I am trying to change the color of a game object's shader (Emission color) to Red and Green with the probability of a 70% of getting the color of green, and a 30% chance of getting the color of red after the thirty seconds, but I cant get it right. Before the thirty seconds, script should be inactive. What am I doing wrong?
public GameObject Rings; public int Time; public Color ColorRed; public Color ColorGreen;
// Use this for initialization
void Start () {
ColorRed = Color.red;
ColorGreen = Color.green;
if (System.Threading.Thread.Sleep (Time>30000))
{
Rings = GameObject.FindGameObjectWithTag ("Rings");
Renderer rend = GetComponent<Renderer> ();
rend.material.shader = Shader.Find ("_EmmissionColor");
rend.material.SetColor (Color.red, Color.green);
}
}
@DPAwesome When a question says "I need a script" "I want" etc with no real description of the errors or troubles they most often get rejected by moderation. It took me a moment to realise you'd had a go as it was hard to see past the question as being just a demand. I've edited it slightly to reflect this. Please keep this in $$anonymous$$d when posting :)
Answer by Positive7 · Feb 27, 2018 at 02:43 AM
This should work :
public GameObject Rings;
public int Time = 30;
public Color ColorRed = Color.red;
public Color ColorGreen = Color.green;
private IEnumerator Start()
{
Rings = GameObject.FindGameObjectWithTag("Rings");
Renderer rend = GetComponent<Renderer>();
yield return new WaitForSeconds(Time); //Creates a yield instruction to wait for a given number of seconds using scaled time.
int rnd = Random.Range(0, 101); //Generate a random number between 1,100
if (rnd < 70)
{
Debug.Log("Green");
rend.material.SetColor("_EmissionColor", ColorGreen);
}
else
{
Debug.Log("Red");
rend.material.SetColor("_EmissionColor", ColorRed);
}
}
Random.Range(0, 101)
is incorrect. The max range (for the int variation of Range()) is exclusive but even so 0 to 100 inclusive is still 101 values. It should be Random.Range(0, 100)
(giving possible values from 0 to 99) or Random.Range(1, 101)
(giving possible values from 1 to 100). $$anonymous$$eep in $$anonymous$$d the code if (rnd <= 70)
is already assu$$anonymous$$g a range of 1 to 100 so only the last option is correct in this case.
To avoid this sort of confusion and because mathematically a percentage is actually a scale value in the range of 0.0f to 1.0f, it's easier and more common to just use float rnd = Random.Range(0.0f, 1.0f);
Note that the max range for float version of Random.Range() is inclusive, unlike the int version and so the range really is 0.0f to 1.0f. Using a float in the range 0.0f to 1.0f of course requires changing the if
condition as well. The Random class also has a value property, which is essentially a shorthand for the common use of Random.Range(0.0f, 1.0f)
float rnd = Random.value; // 0.0f to 1.0f
if (rnd < 0.7f)
{
Debug.Log("Green");
rend.material.SetColor("_EmissionColor", ColorGreen);
}
else
{
Debug.Log("Red");
rend.material.SetColor("_EmissionColor", ColorRed);
}
It may not seem intuitive this way but seasoned programmers and mathematicians would disagree. In this case, it's used trivially but in any calculation, the percentage would need to be divided by 100 so should be implied.
You're right if (rnd <= 70)
should be if (rnd < 70)
. updated my answer but rest of the code is fine. Test :
var cnt = new List<int>();
for (var i = 0; i < 100; i++) cnt.Add(i);
var rnd = Random.Range(0, 101);
for (var i = 0; i < 2147483647; i++)
{
if (cnt.Count <= 0) break;
if (cnt.Contains(rnd))
{
Debug.Log(rnd < 70 ? "70%" : "30%");
cnt.Remove(rnd);
}
rnd = Random.Range(0, 101);
}
Try this.
using UnityEngine;
public class Test : $$anonymous$$onoBehaviour {
// if this is too low, it's possible that the error may never be encountered
public int iterations = 100000;
// consider how this would all work by using a smaller maxRange value, such as 5
public int maxRange = 100;
private void OnEnable() {
TestRandomRange();
}
private void TestRandomRange() {
bool[] possibleValues = new bool[maxRange]; // 100 elements. Last indice is 99
for (int i = 0; i < iterations; i++) {
// return a value in the range of 0 to 100, inclusive
int index = Random.Range( 0, maxRange + 1 ); // remove the +1 to eli$$anonymous$$ate the error
// this will throw an IndexOutOfRange exception because Random.Range()
// could potentially return a value of 100 eventhough the last valid indice is 99.
possibleValues[index] = true;
}
}
}