Reputation: 55
The following code throws an error:
UnityException: Range is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cube : MonoBehaviour
{
public MeshRenderer Renderer;
private float speed = Random.Range(10f, 30f);
void Start()
{
transform.Rotate(speed* Time.deltaTime, 0.0f, 0.0f);
}
void Update()
{
if (Input.GetKeyDown("space"))
{
GetComponent<Renderer>().material.color = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f, 0.5f, 1f);
}
}
}
So I edited it by calling the Range method in start
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cube : MonoBehaviour
{
public MeshRenderer Renderer;
void Start()
{
private float speed = Random.Range(10f, 30f);
transform.Rotate(speed* Time.deltaTime, 0.0f, 0.0f);
}
void Update()
{
if (Input.GetKeyDown("space"))
{
GetComponent<Renderer>().material.color = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f, 0.5f, 1f);
}
}
}
However, I got a bunch of errors, such as error CS1513
, CS1519
, CS8124
etc.
I'm sorry if this sounds really dumb, and I've been trying to fix this by calling Range in Awake()
or googling for similar situations online, but nothing seems to be working.
To summarize:
Random.Range()
in my code?Start()
result in a variety of syntax errors, such as } expected
when I already typed }
?Upvotes: 0
Views: 514
Reputation: 90683
- Where do I call
Random.Range()
in my code?
As Unity tells you within a class derived from MonoBehaviour
it can't be done at field initialization time (which happens before the constructor is executed). The reason is most probably mainly because this instance created by the underlying c++
backend entity component system and accessing the UnityEngine.Random
class from there or in general from other threads is unreliable (see UnityEngine.Random
)
→ Unity already tells you exactly what to do though
call it in
Awake
orStart
instead
you have to assign the value within one of the event message methods Awake
, Start
, etc.
- Why does calling it in
Start()
result in a variety of syntax errors, such as} expected
when I already typed}
?
Because a local variable within a method can not have any access modifiers and you have private
there. So the compiler expects you to first close the Start
method with a }
before using the keyword private
. The rest are just follow up compiler errors.
You want to keep the field declaration at class level and then assign it in Start
private float speed;
private void Start ()
{
speed = Random.Range(10f, 30f);
}
Then you also most probably don't want to rotate only once in Start
but rather move it into Update
in order to get a continous rotation.
private void Update ()
{
transform.Rotate(speed * Time.deltaTime, 0.0f, 0.0f);
...
}
Finally (this is more a general side note) you should change the field type and rather cache
// Already assign vis the Inspector if possible
public Renderer renderer;
private void Awake ()
{
// Get ONCE as fallback
if(!renderer) renderer = GetComponent<Renderer>();
}
and then reuse that reference
private void Update ()
{
...
// it is also preferred to use KeyCode instead of strings
if (Input.GetKeyDown(KeyCode.Space))
{
renderer.material.color = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f, 0.5f, 1f);
}
}
Upvotes: 1
Reputation: 11
Unity works weirdly on the backend. You'll need to declare private float speed;
like in the first snippet. Then in the start/awake method call speed = Random.Range(10f, 30f);
public class Cube : MonoBehaviour
{
public MeshRenderer Renderer;
private float speed;
void Start()
{
speed = Random.Range(10f, 30f);
transform.Rotate(speed* Time.deltaTime, 0.0f, 0.0f);
}
void Update()
{
if (Input.GetKeyDown("space"))
{GetComponent<Renderer>().material.color = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f, 0.5f, 1f); }
}
}
Upvotes: 0