Hi! I’m a bit new to coding. I made this script in which a new level is loaded once the player talks to an NPC, but the level is loaded right away, so the player can’t read the dialogue. Is there any way I can put a few seconds between the time the dialogue loads and the new level loads? I appreciate any help.
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class DialogueLoad : MonoBehaviour {
public string dialogue;
private DialogueMan dMan;
public string[] dialogueLines;
public string loadLevel;
//Usethisfor initialization
void Start () {
dMan = FindObjectOfType<DialogueMan> ();
}
//Updateiscalledonceper frame
void Update () {
}
void OnTriggerStay2D(Collider2D other)
{
if (other.gameObject.name == "Scarlet")
{
if (Input.GetKeyUp (KeyCode.Space))
{
//dMan.ShowBox(dialogue);
if (!dMan.dialogueActive)
{
dMan.dialogueLines = dialogueLines;
dMan.currentLine = 0;
dMan.ShowDialogue();
SceneManager.LoadScene(loadLevel);
}
}
}
}
}
the other way is to have a timer(with an event connected to it) ish, not really a timer in the .net sense.
The following class it what I use to pause before I load my next level.
public class TimerComponent : MonoBehaviour
{
private DateTime mTime;
public delegate void TimeEventHandler(object sender, TimeEventArgs e);
public event TimeEventHandler TimeElapsed;
protected virtual void OnTimeElapsed(TimeEventArgs e)
{
if (TimeElapsed != null)
TimeElapsed(this, e);
}
public void Awake()
{
mTime = DateTime.MinValue;
}
void Update()
{
if (mTime != DateTime.MinValue)
if (DateTime.Now > mTime)
OnTimeElapsed(new TimeEventArgs(DateTime.Now));
}
public DateTime Time
{
get { return mTime; }
set { mTime = value; }
}
}
You will need to hock up the TimeElapsed event for the callback.
The event will not fire until you set Time with the datetime you want the event to fire usually something like
I would definitely recommend using a coroutine for this, as it is much more efficient to keep as much code out of the Update function as possible. Something as simple as this should cover it:
I only use one scene for game play, and it’s not in the update function anyways, it depends on how your code is written, coroutines are not the answer to every solution, but in this case they both work.
It’s what best fits your needs, having an event system as I do, you need to know how to use it properly.
While I concur with your solution, I really don’t think this statement is so straightforward. It depends on what kind of efficiency we’re talking about, though.
In terms of overhead, the player still has to run the code in the coroutine before the frame can end, and when there is a waitForSeconds, some timer loop process is still being run to check whether or not to resume the coroutine. In addition, using coroutines often necessitates additional logic in Update() (or whatever calling function) to prevent more instances of the coroutine from being triggered.
In this specific case, though, since it’s so simple to write the coroutine, the simplicity of the script and the typing time saved are definitely worth it.
You don’t want to be using OnTriggerStay as an IEnumerator. Every single physics step it will try and start that coroutine while the colliders overlap.
Could that instead be OnTriggerEnter?
I’d also like to point out that it isn’t reliable that Input.GetKeyUp will be true at the time of the physics step. You should get those inputs in Update and store it in a variable, and then check that in the event.
You may want to do something like this instead:
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class DialogueLoad : MonoBehaviour {
public string dialogue;
private DialogueMan dMan;
public string[] dialogueLines;
public string loadLevel;
private bool dialogTriggered;
//Usethisfor initialization
void Start() {
dMan = FindObjectOfType<DialogueMan>();
}
//Updateiscalledonceper frame
void Update() {
if(dialogTriggered) {
dialogTriggered = false;
StartCoroutine(startDialog());
}
}
private IEnumerator startDialog() {
//dMan.ShowBox(dialogue);
if(!dMan.dialogueActive) {
dMan.dialogueLines = dialogueLines;
dMan.currentLine = 0;
dMan.ShowDialogue();
yield return new WaitForSeconds(10);
SceneManager.LoadScene(loadLevel);
}
}
void OnTriggerEnter2D(Collider2D other) {
if(other.gameObject.name == "Scarlet") {
dialogTriggered = true;
}
}
}