GUI.TextField submission via "return" key...

Ahoy, I’m having all sorts of trouble trying to get the “enter” key to be recognized while a textField has focus. What i’d like to do is have the user type in his name and then hit the “enter” key directly (vs using the mouse) to call a submit function. Below is where my code is at the moment:

function OnGUI(){
	
	GUI.skin = mySkin;
	
	GUI.SetNextControlName ("MyTextField");
	GUI.FocusControl ("MyTextField");    
	
    stringToEdit = GUI.TextField (Rect (Screen.width/ 2 - 100, Screen.height / 2 - 135, 200, 40), stringToEdit, 25);
    if (GUI.changed == true){
    	print("GUI CHANGED");
    	if (Input.GetKeyDown(KeyCode.Return)){
			print("SubmissionHit");
	}
	}
    if (GUI.Button (Rect (Screen.width/ 2 - 100, Screen.height / 2 - 80, 200, 40), "Submit")) {
		SubmitName();
	}
	if (Input.GetKeyUp(KeyCode.Escape)){
			Application.Quit();
	}
	
}

Using the button on stage works just fine via mouse, but this application is mainly a keyboard input app. Any thoughts?:face_with_spiral_eyes:

What’s the problem you’re having? Is that code not doing anything when Enter or Return are pressed? If so, the problem may be that the return key-press event has already been consumed by the TextField component; you may need to move the test before the control rendering. You may also need to use Event.current.isKey and Event.current.keyCode rather than using the Input class. Or I may be making suggestions related to a different problem that what you’re having… ?

1 Like

You got it, the Return button does nothing at all. I’m interested in the Event code, The return key has no problem being caught by this:

var e : Event = Event.current;
    if (e.isKey) {
        Debug.Log("Detected key code: " + e.keyCode);
    }

So i’m guessing your code

should work fine. But, how would one go about using it? Like this?:

if (Event.current.keyCode == "Return"){
    	print("yay");
    }

Returns an error at the moment.

1 Like
(Event.current.type == EventType.keyDown  Event.current.character == '\n')
1 Like

Not sure that “.character == ‘\n’” is necessarily portable. .keyCode should be more reliable, but Event.keyCode is of type KeyCode, not of type String. Try

if (Event.current.isKey  Event.current.keyCode == KeyCode.Return) { ... }
2 Likes

Why are the simplest things in Unity so hard? No one seems to have posted anything that answers the original question, so I figured it out. Here is the working C# code to accept a Return key press to make the text field go away:

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour
{

bool userHasHitReturn = false;
string stringToEdit = "";

 void OnGUI() {
        Event e = Event.current;
        if (e.keyCode == KeyCode.Return) userHasHitReturn = true;
		else if (false == userHasHitReturn)		stringToEdit = GUI.TextField(new Rect(0,0,100,50), stringToEdit, 25);
    }
}
4 Likes

ccvannorman,

oh… it’s C. C. VanNorman. Got it.

Hey CC,
Thanks for posting your solution. That definitely helped me get my focus to focus on return like I wanted it to. Cool.

I am seeing the same problem. Input.GetKey (KeyCode.Return) no longer works on Macs (either in the editor, standalone builds, or webplayers), however, it still works fine on PCs. I have code that was working fine checking Input.GetKey (KeyCode.Return), but now does not work. This is the first time I have tested the code in Unity 3, so I do not know when this bug showed up in U3.

I also tried Input.GetKey (“return”), Input.GetKey (“enter”), Input.GetKeyUp (KeyCode.Return), and Input.GetKeyDown (KeyCode.Return).

I tried your solution of getting the current event and checking the keyCode directly and it worked fine.

Again, this seems to be a bug on Macs only. (I am currently using U3.3.0f4).

Inside OnGUI, you should check Event.current and not Input.GetKey.

You can either check

if (if (Event.current.type == EventType.KeyDown Event.current.character == ‘\n’)

or

if (Event.current.type == EventType.KeyDown (Event.current.keyCode == KeyCode.Enter || Event.current.keyCode == KeyCode.Return))

you need to do this before GUI.TextField, otherwise the textfield will eat your keydown event

3 Likes

wish this was on answers so I could vote up nicholas post!

Here is an example:

http://forum.unity3d.com/threads/188202-Simple-dynamic-list-editor

1 Like

Thank you Nicholas Francis! :smile:

this solves the individual case, but what about the general case of dealing with input? what if return also does something else in a different context. how can we manage this? ourselves with labouious code? more generally what if we want to bind keys to behaviour in the most general way possible? the simple solution is to allow ‘consuming’ input in a deterministic way… where if someone handles a keypress they can choose that no-one else can handle it. this makes prioritising all the uses of the keys quite straightforward (you will need another update order for inputs…)

maybe there is a solution buried in docs or examples somewhere but its neither obvious through e.g. intellisense nor intuitively named (if it even exists).

Why are the simplest things in Unity so hard?

yeah, i was constantly surprised by this for a while too - i have reached the conclusion that its a combination of absent/shoddy documentation, poor class names and general lack of engine development experience on the team. the editor is fantastic, it really is, and having a reasonably finished editor is much more important than the quality of the engine…

however its more than a little irritating… the example i give of input is a good one. i suspect part of why the current solution is shoddy is the lack of respect for the importance of determinism and ordering in the engine in general which makes it potentially difficult to solve. update orders and having multiple of them for differing contexts (render vs. update is the classic example) and strong deterministic control over it (draw order is a classic example) is extremely valuable… these are realisations from 15+ years ago, nothing new.

they can argue all they want about the difficulty of cross platform but i have tons of native code across the same platform set that works just fine if you do it right then stuff like this becomes much easier… mono is a crude sledgehammer for this purpose and one that hits you a bit as well.

unity uses the component model but why hasn’t it leveraged it here with an ‘inputhandler’ component? they could be iterated over in a custom specified order. sadly it does not seem to be the case that unity allows using components for what they were designed for - we instead have a monolithic entity construction kit with all of the disadvantages of both components and monolithic entities. there is FindObjectsOfType… but the name and its interface scare me off - its a function which indicates that it does something actively instead of retuning the already existing array every component should have internally, it takes a system.type or is a generic which indicates that the implementation is inconsiderate (why not have a generic component base class that provides a correctly typed interface?)

sadly i can go on for a very long time picking flaws and suggesting tried and tested solutions with many advantages…

no i don’t want a job at unity. sorry. i can forsee the rage quit that would follow already :stuck_out_tongue:

you can’t appease everyone semiessessi, I have the same problem right now and am looking for a clean solution.

I’m using windows (draggable windows, one in the other and blah blah blah) And…
This worked for me, Only this one :), Thanks laurie,

Hi,

I got this working kind of. My code follows. You can see I print to the console. But it’s writing to the console 4 times for each single press of the ‘return’ key.

Any ideas ?

Thanks

    private string textFieldString = "text field";

    void OnGUI () {

        Event e = Event.current;
        if (e.keyCode == KeyCode.Return) {       
            print (textFieldString);
        }
        textFieldString = GUI.TextField (new Rect (25, 25, 100, 30), textFieldString);
    }

Found the problem, used this line instead :

if (e.type == EventType.keyDown && e.keyCode == KeyCode.Return)
2 Likes

When I use

void Update() {
        if (InputField.isFocused && InputField.text != "" && Input.GetKey (KeyCode.Return)) {
                /*Message Sending Operations*/
        }

I have to press return key twice in order to send a message. It’s like loosing focus on InputField for the first press and sends on second.
If I try to use something like

void Update() {
        if (InputField.isFocused && InputField.text != "" && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return) {
                /*Message Sending Operations*/
        }

With or without Event.current.type == EventType.KeyDown
It gives this

You must put it in onGUI like this

voidOnGUI ()
{
Evente = Event.current;
if (e.type == EventType.keyDown && e.keyCode == KeyCode.Return) {
}
}

Here is a dedicated class I wrote this morning for text editing. This is for float values but it is easy to modify it to any type you want, or even change it to template one. It displays a value, displays in yellow if it is beeing edited, in red if there is an error, and return a changed flag. The current modification is also cancelable:

public class FloatInputTextfield
{
    public FloatInputTextfield(float val=0.0f)
    {
        Value = val;
    }

    public float Value
    {
        get { return validValue; }
        set
        {
            validValue = currentValue = value;
            text = "" + validValue;
            error = isEdited = false;
        }
    }

    static GUIStyle style = null;

    float validValue = 0.0f;
    float currentValue = 0.0f;
    bool isEdited = false;
    bool error = false;
    string text = "";

    public bool OnGUI(Rect area)
    {
        if (style == null) // Has to be done with OnGUI call
        {
            style = new GUIStyle(GUI.skin.textField);
            style.alignment = TextAnchor.MiddleCenter;
        }

        bool changed = false;
        Event e = Event.current;
        if (e.type == EventType.keyDown)
        {
            if (e.keyCode == KeyCode.Return)
            {
                Value = currentValue;
                changed = true;
            }
            else
            if (e.keyCode == KeyCode.Escape)
            {
                Value = validValue;
            }
        }
        Color saved = GUI.color;
        GUI.color = error ? Color.red : (isEdited ? Color.yellow : saved);
        text = GUI.TextField (area, text, style);
        error = !float.TryParse (text, out currentValue);
        GUI.color = saved;
        isEdited = error || validValue != currentValue;

        return changed;
    }
}

Then, you only have to use it this way:

FloatInputTextfield myFloatValue = new FloatInputTextfield(5.0);
void OnGUI()
{
    float v = 0.0f;
    if(myFloatValue.OnGUI(new Rect(10,10,50,30)))
         v= myFloatValue.Value;
}