I’m trying to create signposts for the tutorial stage of my game (which is this WIP), and I’m trying to make it so that when the player hits the “Enter” key, the message will display in a while-loop until they hit the “A” key. The reason I want the while loop is so that movement stops by halting the program.
The only problem is that this isn’t working! The message never displays, and the program freezes - no input is being registered and an apparent infinite loop is happening.
This is the code I’m using. I’m using GUIText objects for the actual text, and just enabling/disabling them when appropriate.
[FONT=Menlo]using UnityEngine;
using System.Collections;
public class TutorialMessageController : MonoBehaviour
{
// Set GUIText strings for caption, body, and continue
public GUIText caption;
public GUIText body;
// Private boolean to tell when to display messages
private bool showMessage = false;
private bool display;
void Start()
{
caption.enabled = false;
body.enabled = false;
}
// If player collides with message zone, show it
void OnTriggerEnter(Collider msg)
{
if(msg.gameObject.tag == "Player")
{
showMessage = true;
}
}
// When player leaves trigger zone, don't show it
void OnTriggerExit()
{
showMessage = false;
}
// Print text in update loop
void Update()
{
// If player presses enter, display sign contents
if(Input.GetKeyDown(KeyCode.Return) showMessage)
{
display = true;
showMessage = false;
}
if(display)
{
DisplayMessage();
}
}
void DisplayMessage()
{
// When display is true, display message
while(!Input.GetKey(KeyCode.A))
{
caption.enabled = true;
body.enabled = true;
}
display = false;
}
}
[/FONT]
My question is, why? I know I’ve used While loops in other engines exactly like this, just fine, so what’s going on? Can anyone enlighten me as to why Unity doesn’t like this, and if so, is there another way I can get the program to halt so that the player has to press something for the message to go away?
From what I can tell, it’s being caught in an infinite loop at the while loop, but since it’s constantly looping through that, it’s not giving the program the opportunity to catch any other input signals. (Just my guess though.)
My best guess for what I’d do would be to make it an if-statement on if they’ve hit A again, while checking against other booleans. If you need to freeze the player, get whatever is controlling the player and set move speed to zero, lock movement, etc (some work around for that). That would be my best guess to accomplish that since the while loop isn’t working as you intend.
That can’t work since you coded an infinite loop. If the A key isn’t down, then it just loops forever since there’s no possibility of the key ever being pressed at that point, since the loop won’t exit and no more code will run. You can never halt or pause Update in any way, so I’d recommend using coroutines instead.
I took _Nick’s suggestion and updated my code to the following. It works as expected!
using UnityEngine;
using System.Collections;
public class TutorialMessageController : MonoBehaviour
{
// Set GUIText strings for captionMessage, bodyMessage, and continue
public GUIText captionMessage;
public GUIText bodyMessage;
public GUIText continueMessage;
public GUIText readMeMessage;
public GameObject player;
// Private boolean to tell when to display messages
private bool showMessage = false;
private bool display;
private PlayerController pScript;
// Disable all GUITexts
void Start()
{
captionMessage.enabled = false;
bodyMessage.enabled = false;
continueMessage.enabled = false;
readMeMessage.enabled = false;
pScript = player.GetComponent<PlayerController>();
}
// If player collides with message zone, show it
void OnTriggerEnter(Collider msg)
{
if(msg.gameObject.tag == "Player")
{
showMessage = true;
}
}
// When player leaves trigger zone, don't show it
void OnTriggerExit()
{
showMessage = false;
}
// Print text in update loop
void Update()
{
// If showMessage is true, display readmeMessage
if(showMessage)
{
readMeMessage.enabled = true;
}else
{
readMeMessage.enabled = false;
}
// If player is in sign zone and presses enter, display sign contents
if(Input.GetKeyDown(KeyCode.Return) showMessage)
{
display = true;
showMessage = false;
}
if(display)
{
DisplayMessage();
}
}
void DisplayMessage()
{
// Stop player movement
pScript.rigidbody.velocity = Vector3.zero;
pScript.rigidbody.Sleep();
// Display message
captionMessage.enabled = true;
bodyMessage.enabled = true;
continueMessage.enabled = true;
// When player exits signpost, stop displaying contents
if(Input.GetKeyDown (KeyCode.A) display)
{
display = false;
captionMessage.enabled = false;
bodyMessage.enabled = false;
continueMessage.enabled = false;
}
}
}
@Eric5h5: Ah, that makes sense, I see how that wouldn’t work now. I’ve been up far too long, perhaps I’ve burned out my brain. But at least I got my solution pretty quick!
Thanks for the quick responses everyone. You all get a beer on me!