How to make GameObjects appear with events??

Cutscene I am currently working on…

background image
sleeping player sprite
dialogue box
floating zzz animation
fade in animation

I want the dialogue box to appear after 10 seconds of hitting the Play button instead of it appearing immediately. How can I achieve this?

I’ll post the code I’m using below currently.

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

//C# Script File "Dialogue"
public class dialogue : MonoBehaviour {

    // Variables "dBox" & "dText"
    public GameObject dBox;
    public Text dText;
  

    // Variable "dialog Active"
    public bool dialogActive;

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {



        if (dialogActive && Input.GetKeyDown (KeyCode.Space))
        {
            dBox.SetActive (false);
            dialogActive = false;

        }
    }

    public void ShowBox(string dialogue)
    {
       
      
            dialogActive = true;
            dBox.SetActive (true);
            dText.text = dialogue;
       
    }
}

The most simple way would be to use Invoke with the delay.

using UnityEngine;
using UnityEngine.UI;

public class Dialogue : MonoBehaviour
{
    public GameObject dBox;
    public Text dText;

    private string dialogue;

    void Start()
    {
        dialogue = "Hello World";
        Invoke("ShowBox", 10f);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && dBox.activeInHierarchy))
        {
            dBox.SetActive(false);
        }
    }

    void ShowBox()
    {
        dBox.SetActive(true);
        dText.text = dialogue;
    }
}

Note that your dialogActive bool is redundant since you can just use “activeInHierarchy” or “activeSelf”

The disadvantage of Invoke is that it uses a string, so if you want to avoid that you could do some condition checks in Update like this:

using UnityEngine;
using UnityEngine.UI;

public class dialogue : MonoBehaviour
{
    public GameObject dBox;
    public Text dText;

    private bool isShowBoxDone;

    void Update()
    {
        if (isShowBoxDone || Time.timeSinceLevelLoad < 10f)
        {
            return;
        }
        else if (!dBox.activeSelf)
        {
            ShowBox("Hello World");
        }
        else if (Input.GetKeyDown(KeyCode.Space))
        {
            dBox.SetActive(false);
            isShowBoxDone = true;
        }
    }

    void ShowBox(string dialogue)
    {
        dBox.SetActive(true);
        dText.text = dialogue;
    }
}

And finally there is the more advanced Coroutine example like this:

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

public class dialogue : MonoBehaviour
{
    public GameObject dBox;
    public Text dText;

    IEnumerator Start()
    {
        yield return new WaitForSeconds(10f);
        ShowBox("Hello World");
        while (!Input.GetKeyDown(KeyCode.Space))
        {
            yield return null;
        }
        dBox.SetActive(false);
    }

    void ShowBox(string dialogue)
    {
        dBox.SetActive(true);
        dText.text = dialogue;
    }
}

The first code you posted returned an "Operator ‘&&’ cannot be applied to operands of type ‘UnityEngine.KeyCode’ & ‘Bool’

The other two compiled just fine without errors but when I played the scene there was no delay in showing the Dialogue Box… hmm

even when I changed it to 100f (not sure how many seconds 10 or 100f would last but the dialogue box is there as soon as I start the Game)

Sorry the first one was missing a closing parenthesis.

Have you placed this script on another GameObject that is always active? My code does not initialize the dBox as inactive so you should either include that in the script or disable it in the inspector.

Here it is included:

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

public class dialogue : MonoBehaviour
{
    public GameObject dBox;
    public Text dText;

    IEnumerator Start()
    {
        dBox.SetActive(false);
        yield return new WaitForSeconds(10f);
        ShowBox("Hello World");
        while (!Input.GetKeyDown(KeyCode.Space))
        {
            yield return null;
        }
        dBox.SetActive(false);
    }

    void ShowBox(string dialogue)
    {
        dBox.SetActive(true);
        dText.text = dialogue;
    }
}

10f = 10 seconds so 100 is 1 min 40 sec if Time.timeScale = 1.

Hey thanks a lot man this worked perfectly.

Since I’m using this for my intro cutscene is there anyway where I can set other actions to trigger when pressing spacebar??

for example

I added to your code to make another dBox pop up 5 seconds after the first one goes away… how can I make it so when the user presses spacebar for the second time to also make the floating zzz’s animation go away? would I have to write a new C# script file and add it to the floating zzz’s animation?

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

public class zzz : MonoBehaviour
{
    public GameObject floatingzzz;

    IEnumerator Start()
    {
        floatingzzz.SetActive(false);
        while (!Input.GetKeyDown(KeyCode.Space))
        {
            yield return null;
        }

    }

}

Would I write something like this? and then drag it onto the floatingzzz’s in inspector?

There are many ways of doing the same thing. The important thing is to make it easy to read for yourself and edit later. It might make sense to add to the existing script since this is a chain of events.

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

public class dialogue : MonoBehaviour
{
    public GameObject dBox;
    public Text dText;

    IEnumerator Start()
    {
        dBox.SetActive(false);
        yield return new WaitForSeconds(10f);
        ShowBox("Dialogue 1");
        yield return StartCoroutine(WaitForSpaceBar());
        dBox.SetActive(false);
        yield return new WaitForSeconds(5f);
        ShowBox("Dialogue 2");
        yield return StartCoroutine(WaitForSpaceBar());
        // Stop Animation
        dBox.SetActive(false);
    }

    IEnumerator WaitForSpaceBar()
    {
        while (!Input.GetKeyDown(KeyCode.Space))
        {
            yield return null;
        }
    }

    void ShowBox(string dialogue)
    {
        dBox.SetActive(true);
        dText.text = dialogue;
    }
}

oh snap it worked… i’ma test this with a bunch of other stuff, thanks a bunch man

You’re welcome. If you are not familiar with Coroutines you may want to read more about them since they can lead to some strange bugs or crashes (infinite loops) if used incorrectly.

you’ve created a monsta

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

public class cutscene : MonoBehaviour
{
    public GameObject dBox;
    public Text dText;
    public GameObject floatingzzz;
    public GameObject sleeping_charg;
    public GameObject seikog;

    IEnumerator Start()
    {
        Debug.Log(Time.timeScale);
        dBox.SetActive(false);
        yield return new WaitForSeconds(10f);
        ShowBox("Seiko: ...");
        yield return StartCoroutine(WaitForSpaceBar());
        dBox.SetActive(false);
        floatingzzz.SetActive (false);
        yield return new WaitForSeconds(2f);
        sleeping_charg.SetActive (false);
        seikog.SetActive (true);
        ShowBox("Seiko: How long was I asleep?");
        yield return StartCoroutine(WaitForSpaceBar());
        dBox.SetActive(false);
    }

    IEnumerator WaitForSpaceBar()
    {
        while (!Input.GetKeyDown(KeyCode.Space))
        {
            yield return null;
        }
    }

    void ShowBox(string dialogue)
    {
        dBox.SetActive(true);
        dText.text = dialogue;
    }
}

Yes it could always be improved :slight_smile:

i almost think doing this in visual studio without the unity editor would be easier somehow =/

edit: nevermind unity makes it way easier but
as far as understanding what every single line of code actually does starting from scratch would be easier to understand

Soo now I have finished my first cutscene!!

I’m working on the first level and I have a warp set up, I tried using the same code to make a dialogue box pop up when warping to a certain area of the level but it doesn’t seem to work…

I tried changing IEnumerator Start to void Update but then I got an error “a get or set accessor expected”
on the first line

edit:
I just tried it with IEnumerator Update and it didn’t work either

Yes Update can’t return IEnumerator.

The problem you have is probably with “if (cameram.gameObject.transform.position.y == (5))”.
First of all it is only evaluated once when the behaviour Starts and you are doing an equality check on a float unboxed from an int32 so the result is unreliable. You may want to use Mathf.Approximately() instead or just a greater than or less than operator.
If you are trying to get the transform from the main camera you can use the built in getter “Camera.main”.

You don’t need the line "Debug.Log(Time.timeScale) by the way. It was a line I forgot to remove.

I accidentally deleted the main camera from the scene and Idk how to get it back so Camera.main doesn’t work

btw, this is my warp code, i got it from a youtube video

I’m going to try to make a similar code to set to an object collider to have the dbox pop up

now I’m getting this error with this code
Cave\dialoguebox.cs(7,7): Error CS1624: The body of ‘dialoguebox.OnTriggerEnter2D(UnityEngine.Collider2D)’ cannot be an iterator block because ‘void’ is not an iterator interface type (CS1624) (Assembly-CSharp)

Oh okay I couldn’t have a yield return in there that’s why

Yesss it works now!

Here’s the code…

Now I just have to figure out how to make it so the box doesn’t keep pop up again when you walk into the zone after pressing spacebar…

also interesting to note is that spacebar stops working to make the dbox go away after the first time… hmm

New Question!

I have 2 Zones, say A & B.

Walk through zone A > dBox pops up > Hit spacebar > dBox goes away > Teleport to battle area > Battle ends > Return warp > continue…
Walk through zone B > dBox pops up > Hit spacebar > dBox goes away…

My two scripts do this just fine but if the player happens to cross zone B without crossing zone A… then Hit’s spacebar, he will be ported to a battle area… It should not do that. I only want the player to be ported to the battle area after hitting spacebar when the dBox of zone A pops up. here are the 2 scripts

Actually… to simplify the problem a bit…

The player doesn’t even have to walk through the zone at all… As soon as hit the play button in the scene and press spacebar, he is ported to the battle zone xD

oooh this must be because I have a dialogue manager now that the dBox is in!!!
i’m gonna try to fix this

Ok soo I put everything else in other scripts to simplify this dialogue box bug…

Here’s the short code

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

public class hotspot : MonoBehaviour {

    public GameObject dBox;
    public Text dText;
    public GameObject dialogueZone;

    IEnumerator Start() {
        yield return StartCoroutine (WaitForSpaceBar ());
        dBox.SetActive (false);
            }

    void OnTriggerEnter2D(Collider2D other){
  
        ShowBox("Seiko: What happened to the others?");
    }

    IEnumerator WaitForSpaceBar()
    {
        while (!Input.GetKeyDown(KeyCode.Space))
        {
            yield return null;
        }
    }

    void ShowBox(string dialogue)
    {
        dBox.SetActive (true);
        dText.text = dialogue;

    }
}

Pretty much as soon as the game starts, if I press spacebar, the “life” that this code gives to the spacebar button to remove the active dialogue box, dies.

I’m not sure where to start on this one.

UPDATE: Fixed this by creating a LOOP

New code

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

public class hotspot : MonoBehaviour {

    public GameObject dBox;
    public Text dText;
    public GameObject dialogueZone;
    public GameObject constantlooper;

    IEnumerator Start() {
        while (constantlooper.activeInHierarchy) {
            yield return StartCoroutine (WaitForSpaceBar ());
            dBox.SetActive (false);
        }
    }

    void OnTriggerEnter2D(Collider2D other){

        ShowBox("Seiko: What happened to the others?");
    }

    IEnumerator WaitForSpaceBar()
    {
        while (!Input.GetKeyDown(KeyCode.Space))
        {
            yield return null;
        }
    }

    void ShowBox(string dialogue)
    {
        dBox.SetActive (true);
        dText.text = dialogue;

    }
}