Getting string from InputField (On Value Changed())

Hello All

I am new to Unity. Most probably I miss very basic point but for the last few days I am stuck at this point and can’t see the mistake. I hope someone can show me where it is.

I use PhotonNetwork PUN for a multiplayer game and I follow the tutorials on the PUN web site.

I follow the code written in the web site above, but still couldn’t make it. Probably, I do something wrong with Input Field and On Value Changed().

Here is my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;

[RequireComponent(typeof(InputField))]
public class NicknameInputField : MonoBehaviour
{
   
    const string playerNamePrefKey = "PlayerName";
    // Start is called before the first frame update
    void Start()
    {
        string defaultName = string.Empty;
        InputField _inputField = this.GetComponent<InputField>();
        if (_inputField!=null)
        {
            if (PlayerPrefs.HasKey(playerNamePrefKey))
            {
                defaultName = PlayerPrefs.GetString(playerNamePrefKey);
                _inputField.text = defaultName;
            }
        }

        PhotonNetwork.NickName =  defaultName;      
    }
    public void SetPlayerNickName(string value)
    {
        if(string.IsNullOrEmpty(value))
        {
            Debug.LogError("Player Name is empty");
            return;
        }
        Debug.Log(PlayerPrefs.GetString(playerNamePrefKey));
        PhotonNetwork.NickName = value;
        PlayerPrefs.SetString(playerNamePrefKey,value);
    }

}

and here is the screenshot of editor for you to see On Value Changed() part.

NicknameInputField script is attached to empty object NicknameManager. I choose SetPlayerNickname after putting NicknameManager object into Input Field.

I did some Debug.Log and found out that string value in the function is always null. Also did some research on the internet and saw some posts about dynamic section and static section of On Value Changed(). But as you can see there is no such thing in my drop down menu.

Sorry for the long and crowded post. I am sure the mistake will be very small and basic but i can’t see it for days.

1 Like

nobody knows? :frowning:

I notice the “OnValueChanged” box on your Input Field has parentheses with nothing between them. That looks similar to a problem recently reported by some other users:

Some UI elements don’t have type
Slider On Value Changed broken in OSX

Unfortunately, no one has come up with an answer in either of those threads, either. It’s possible it’s a bug in a specific version of Unity?

This thread is a bit old but I can answer :slight_smile:

Usually the string value you put between parentheses won’t bring the the value from the input. But gives you which what you’ve put in the inspector which is empty.

That’s what you want

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;
[RequireComponent(typeof(InputField))]
public class NicknameInputField : MonoBehaviour
{
    //Assuming that the script is'nt on the Input Object
   public GameObject inputFieldObj; //Add this
    const string playerNamePrefKey = "PlayerName";
    // Start is called before the first frame update
    void Start()
    {
        string defaultName = string.Empty;
        InputField _inputField = this.GetComponent<InputField>();
        if (_inputField!=null)
        {
            if (PlayerPrefs.HasKey(playerNamePrefKey))
            {
                defaultName = PlayerPrefs.GetString(playerNamePrefKey);
                _inputField.text = defaultName;
            }
        }
        PhotonNetwork.NickName =  defaultName;    
    }
    public void SetPlayerNickName(//Leave that empty)
    {
       
        InputField inputField = inputFieldObj.GetComponent<InputField>();
         string value = inputField.text;
        if(string.IsNullOrEmpty(value))
        {
            Debug.LogError("Player Name is empty");
            return;
        }
        Debug.Log(PlayerPrefs.GetString(playerNamePrefKey));
        PhotonNetwork.NickName = value;
        PlayerPrefs.SetString(playerNamePrefKey,value);
    }
}
1 Like

Hello.
I have been studying the same tutorial, and I had a tricky bug about the same issue.
After selecting the script, I chose the same option as you — setPlayerNickName(string) — and it didn’t work. I had to select a similar option above, but withouth parenthesis.

Why could that happen? Sincerely I don’t know. But it seems it could be related to this line of code:

InputField _inputField = this.GetComponent();

Because it is about its own input field. So, I think this is why it is necessary to attach the script to the same Name InputField – Game Object –

Now, I tested it attaching the script to the GameObject – empty Game Object --, drag and drop to the indicated slot. It didn’t work.

I tried again the same but attaching the script to the Name InputField – Game Object – too and, (although it is a weird thing), it worked.

I hope it can help you.

9 Likes

THANK YOU SO MUCH. This worked to me! Just needed to find the method without the parenthesees.

1 Like

I’m glad it worked for you! :slight_smile:

2 years old and this thread still saving lives! Using the function without parenthesis worked perfect for me.

1 Like

The option without parenthesis doesn’t appear to me :frowning:

1 Like

Considering I just had the same question and nobody went through the “why” I’ll leave an explanation for what’s going on. The function with parenthesis, as you can see in the editor, is meant to be used with static parameters, while the one without parenthesis works with the dynamic string coming from the input (which in this case is usually what we want).

But definitely, thanks for pointing out and saving me a headache or two.

4 Likes

I just stumbled upon this thread by accident and couldn’t believe it took nearly a year for someone to explain this simple thing :open_mouth: Kudos to @mohr023 for doing so.

Just to expand on that, allow me to go into a bit more detail for those who might need it:

You will notice that only public functions appear in the dropdown as selectable functions to call. Also worth noting is that functions must match a predefined function signature before it will display. For instance:
public void MyFunc(string value){} is fine and will show up just fine as something you can choose.

void MyFunc(string value){};
public void MyFunc(string value1, string value2, string value3){}

These two functions will not appear in the list.
So to those of you who say “The function doesn’t appear for me” that is why…

If you choose a function under the “Static Parameters” list (Check the drop down, you will see it written there :wink: ) then you will see a field in the inspector where you can enter a value. Let’s say “Hallo world”. What you are saying here is:
Whenever the value of this field changes, please call this function and send it the value “Hallo world” every time.

Now, if you look a little higher up you will see functions listed under “Dynamic String” (See the image 6 posts above this one). If you select one of these then you won’t get the option of specifying a value in the inspector any more because what you are saying when you choose one of THESE functions is:
Whenever the value of this field changes, please call this function and send it whatever the current value of this field is.

So to put it simply: If you set the value in the inspector then that is the value the function will get forever. If you want to get the "current" value each time it changes then you need to initialize the text/ bool/ int/ whatever via code, not via the inspector. That should make it easy to remember

And there you go. Mystery solved

5 Likes

Here is how to do what you want through code:

public TMP_InputField nameInputField;

private void Start()
{  
    nameInputField.onValueChanged.AddListener(UpdateInputField);
}

void UpdateInputField(string data)
{
    print(data);
}

Data is the value of the input box. Note that I’m using TextMeshPro so just change the type of input field your using if needed.

If you want more parameters in the UpdateInputField function then just do it like this:

public TMP_InputField nameInputField;

private void Start()
{
    nameInputField.onValueChanged.AddListener((data) => { UpdateInputField(data, 5); });
}

void UpdateInputField(string data, int otherData)
{
    print(data);
}
5 Likes

I was experiencing a very weird bug related to ASYNC activity where the event would have the previous value unless backspace was pressed.

It turns out the TMP Textbox calls on changed BEFORE setting the value that would be returned by GetComponent<TMP_Text>().text;

I added a 20ms delay to allow the back end value to catch up and it seems to work fine now…

public async void EmailAddress_Changed()
    {
        await Task.Delay(20);
        var text = Email;
        Debug.Log($"Email changed to {text}.");

        var auth = EpicBattleClient.Instance.InputBinding.Authentication;
        auth.Email = text;

        var exists = await EpicBattleClient.Instance.CheckEmailExists();
        Debug.Log($"Email exists {exists}");

        LoginButtonText = exists ? "LOGIN" : "JOIN";
    }

If you look again at the tutorial, you’ll be able to see that you have to use dynamic string, not static parameters.
7968690--1022085--upload_2022-3-17_1-5-40.png

That’s why you shouldn’t use the one with parentheses.

you have to choose it below the Dynamic String of dropdown not the static

Thanks. Just what I was looking for.

this is the code that you missing!!
using UnityEngine.UI;
:slight_smile:
hope you to enjoye…

yes sir that was the answer, thanks!!

1 Like