title | marp | paginate |
---|---|---|
Unity advanced 1. Actions and delays |
true |
true |
- The straightforward approach
// First, get the GameObject GameObject lightbulb = GameObject.Find("Lightbulb"); // Then, get the script component "SetColor" lightbulbSetColor = lightbulb.GetComponent<SetColor>(); // Then, call the public method SetColorToRed lightbulbSetColor.SetColorToRed();
- Script Reference: SendMessage
- Another way for calling a method in a GameObject
- No need to get the corresponding component, or even make sure the method exists in the first place
// Calls the function ApplyDamage with a value of 5 // Every script attached to the game object // that has an ApplyDamage function will be called. gameObject.SendMessage("ApplyDamage", 5.0);
- Note: it can only take in ONE argument maximum
- You can bypass this restriction by making the argument an array or a class, etc.
- The straightforward approach
- You need helper variables for this, can make for a hard-to-parse code block
private float nextActionTime = 0.0f;
public float period = 0.1f;
void Update () {
if (Time.time > nextActionTime )
{
nextActionTime = Time.time + period;
// execute block of code here
}
}
- Script Reference: Invoke
- Use Invoke if you want to execute a method after a given time delay
- Note: You can't pass any arguments to invoked methods.
void Start() { Invoke("SpawnObject", 2); } void SpawnObject() { Instantiate(target, new Vector3(0, 2, 0), Quaternion.identity); }
- Script Reference: InvokeRepeating
- InvokeRepeating is an extension of invoke: if you want to execute something after a delay, and then every x seconds
void Start() { InvokeRepeating("SpawnObject", 2.0f, 1.0f); // after two seconds, execute every one second } void SpawnObject() { float x = Random.Range(-2.0f, 2.0f); float z = Random.Range(-2.0f, 2.0f); Instantiate(target, new Vector3(x, 2, z), Quaternion.identity); }
- To stop the process from repeating, use
CancelInvoke("SpawnObject");
- Manual: Coroutines
- A function that is executed until the
yield
statement is reached, and then continued on the next frame- On the next frame, we don't start from the beginning, but rather after the
yield
statement - Thus, we can do something, and then continue on the next frame or even after a specified time delay
- Excellent for sequenced events (cutscenes!)
- On the next frame, we don't start from the beginning, but rather after the
- Unity Learn: Coroutines
- Coroutines are functions with return type
IEnumerator
IEnumerator TrivialCoroutine() { yield return null; }
- In coroutines, you can't
return
- you have to useyield return
yield return null;
yield return new WaitForSeconds(5.0f);
- ...
- Note: To end a coroutine, you can use
yield break;
IEnumerator Fade()
{
Color c = renderer.material.color;
for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
{
c.a = alpha;
renderer.material.color = c;
yield return null;
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)) // press space to (re)start coroutine
{
StartCoroutine(Fade());
}
}
- After coroutine is started, it will execute until it has reached its end
IEnumerator ChangeColorToRandom()
{
lähetti.SendMessage("SetColorToRandom");
Debug.Log("eka");
yield return new WaitForSeconds(2f);
lähetti.SendMessage("SetColorToRandom");
Debug.Log("toka");
yield return new WaitForSeconds(2f);
lähetti.SendMessage("SetColorToRandom");
Debug.Log("kolmas");
yield return new WaitForSeconds(2f);
}
- This coroutine will send a message, then wait for a given time, and then continue on to the next message
IEnumerator ExecuteAfterTime(float time)
{
yield return new WaitForSeconds(time);
doStuffAfterDelay();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(ExecuteAfterTime(10));
}
}
IEnumerator fade;
// create variable for the coroutine function
// so we can refer to it in StartCoroutine and StopCoroutine
void Start()
{
fade = Fade();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
StartCoroutine(fade); // starts or continues coroutine if already started
if (Input.GetKeyDown(KeyCode.Backspace))
StopCoroutine(fade); // pauses coroutine if already started
}
- You can call other coroutines inside coroutines like this:
IEnumerator SetColor(float time)
{
lähetti.SendMessage("SetColorToRandom");
yield return new WaitForSeconds(time);
}
IEnumerator ChangeColorToRandom()
{
yield return SetColor(2f);
yield return SetColor(15f);
yield return SetColor(3f);
}
...
StartCoroutine(ChangeColorToRandom());