1. Actions and delays

Calling a method from another GameObject

  • 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();
    

Sending messages

  • 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.

Doing something every x seconds

  • 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
  }
}

Invoke

  • 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);
        }
    

InvokeRepeating

  • 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");

Coroutines

  • 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!)
  • Unity Learn: Coroutines
  • Coroutines are functions with return type IEnumerator
    IEnumerator TrivialCoroutine()
    {
        yield return null;
    }
    
  • In coroutines, you can't return - you have to use yield return
    • yield return null;
    • yield return new WaitForSeconds(5.0f);
    • ...
  • Note: To end a coroutine, you can use yield break;

Example: Keep executing something after a 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

Example: Do three things in a sequence


    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

Example: Execute something after a time delay

IEnumerator ExecuteAfterTime(float time)
{
    yield return new WaitForSeconds(time);
    doStuffAfterDelay();
}

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        StartCoroutine(ExecuteAfterTime(10));
    }
}

Example: Pause coroutine, then continue

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
}

Example: Coroutine of coroutines

  • 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());