Input.inputString - What am I doing wrong?

I have a simple menu screen, with the following options;

[N]ew Game

[P]layer Name

[Q]uit

I poll Input.GetKeyDown within update() to check for user input, N starts a new game and Q will quit the game fine, P is meant to allow the player to edit the Player Name field.

This all works fine, except when the user presses “P” the Character “P” is also appended to “Player Name” each time.

void Update () {
	
	if (playerNameEditable == true) {

			foreach (char c in Input.inputString) {
				if (c == "\b"[0]) {
					if (guiText.text.Length != 0) {
						guiText.text = guiText.text.Substring(0, guiText.text.Length - 1);
					}
				}
				else {
					if (c == "

"[0] || c == “\r”[0]) {
print("User entered his name: " + guiText.text);
playerName = guiText.text;
playerNameEditable = false;
}
else {
guiText.text += c;
}
}
}
}
else {

			if (Input.GetKeyDown (KeyCode.N)) {
				Application.LoadLevel ("Main");
			}
			
			if (Input.GetKeyDown (KeyCode.P)) {
				playerNameEditable = true;
			}
			
			if (Input.GetKeyDown (KeyCode.Q)) {
				Application.Quit ();
			}

		}
}

What is the best way to avoid this and can someone explain to me why does this happen? When I look at the script, I see the playerName field being set to editable towards the end of the update cycle and I was not expecting the P to appear on next cycle… Even if you press several other letters quickly before pressing P the several others letters are not appended, just the P each time…

Surely [or not?] it has already run the code above and decided not to add P to string as it fails the playerNameEditable == True condition to do this? It is only after this line that it is set to true.

Would appreciate any enlightenment - Clearly I am misunderstanding how the code is processed at a fundamental level! :s

Hitting P sets playerNameEditable to true (so you’ll start entering the player’s name), but will also push the char ‘P’ to Input.inputString, ready for the next time Update() is called. There are a few ways around this, but the simplest to wrap your head around would be to handle the first frame during which playerNameEditable is true, and manually ignore the first character in Input.inputString (or since you’re running at high framerate, just skip processing input on the first frame playerNameEditable is true).

private bool firstFrameProcessingInput;

void Update () {

    if (playerNameEditable == true) {
        //ignores the first frame during which playerNameEditable is true
        if (firstFrameProcessingInput) {
            firstFrameProcessingInput = false;
            return;
        }

        foreach (char c in Input.inputString) {
        if (c == "\b"[0]) {
            if (guiText.text.Length != 0) {
                guiText.text = guiText.text.Substring(0, guiText.text.Length - 1);
            }
        }
        else {
            if (c == "

"[0] || c == “\r”[0]) {
print("User entered his name: " + guiText.text);
playerName = guiText.text;
playerNameEditable = false;
}
else {
guiText.text += c;
}
}
}
}
else {

        if (Input.GetKeyDown (KeyCode.N)) {
            Application.LoadLevel ("Main");
        }

        if (Input.GetKeyDown (KeyCode.P)) {
            playerNameEditable = true;
            firstFrameProcessingInput = true; //set this to true whenever playerNameEditable is set to true
        }

        if (Input.GetKeyDown (KeyCode.Q)) {
            Application.Quit ();
        }

    }
}