0
\$\begingroup\$

I am having a problem in unity setting up a search field. I will post pictures down reggarding my problem but first let me quickly explain what is going on.

I have input element in my ui and i have working search function ready to use. The problem is that the string i feed my search function with is assigned from the inputfield text element value, which appears to be always one step behind.

What i mean is when I type "Wooden door" inputfield value is "Wooden doo".

It is quite annoying and I have no idea what is going on. Please point me into right direction.

Let me post the pictures with quick descriptions.

My UI: My UI

My problem (item I am looking for is named "Wooden door"): Problem pt1

Second image of my problem (door item should not be present):

Problem pt2

Finaly my ui settings and code:

Calling when OnChange

Assigning value here: enter image description here

My search control script:

using UnityEngine;
using UnityEngine.UI;
public class SearchControl : MonoBehaviour
{
public InputField inputField;
public Text searchInput;

private void Start()
{
    inputField = GetComponent<InputField>();
    searchInput = inputField.textComponent;
}

public void Search()
{
    if (searchInput == null)
    {
        Debug.LogWarning("Can't find search field.");
        return;
    }
    //TODO: text value is always one letter behind.
    string searchVal = searchInput.text;
    Debug.Log("Searching value: " + searchVal);

    CraftingManager.instance.RenderSearchedRecipes(searchVal);
}
}

I think there is some kind of character "verification" going on there and the real value of that text field is really one letter behind (since i assign it befor it gets verified). But that is not acceptable and I have no idea what can i do to avoid it. Thank you for any help!

\$\endgroup\$
  • \$\begingroup\$ Please include your code as text, not as an image, showing the full context (so we can see how your variables like searchInput are declared & populated). Have you tried searching for past Q&A with users experiencing a similar issue? \$\endgroup\$ – DMGregory Jul 26 at 11:52
  • \$\begingroup\$ Will edit in sec... Edit: Done.. I tried and i could not find anything for few days so i just moved on to another issue. But now I need to finish it. What I found is that if you are using unity.ui input field you should try to use callback OnValidateInput leaving link at the end of comment. But I am not sure how to implement that since it is not visible in the inspector. docs.unity3d.com/ScriptReference/… \$\endgroup\$ – Lucián Blažek Jul 26 at 12:03
  • 1
    \$\begingroup\$ Ok, so this is my guess, but I don't have enough information to know for sure. Could it be that searchInput is referencing the actual text field rather then the InputField? If so, when editing text, Unity first updates it's text property of the Inputfield. Then it sends the OnChanged event (which btw can contian a string with the new value as a parameter). And then it updates the actual label (i.e. the text visible on screen). So if searchVal is of type Text instead of type InputField, this is expected behaviour. n.v.m. with the edit now I do know for sure, thats the problem :p \$\endgroup\$ – troien Jul 26 at 12:09
  • \$\begingroup\$ Yep that was it as @JustinMarkwell also pointed out. It was just confusing for me to use the input field text variable and not the actual text field inside of it. Anyway i will move onto text mesh pro next time. I heard it is much clearer. Definitely thank you for you contribution! \$\endgroup\$ – Lucián Blažek Jul 26 at 12:18
2
\$\begingroup\$

Misleading variable names strike again.

searchInput, despite "input" in its name, isn't pointing to your input field that's receiving the new text. It's the display text object.

The display text field does not find out about the new string until after the change has been handled by your onValueChanged script, because your script might have changed the text that you want the user to see (say, deleting forbidden characters or adding formatting to a phone number)

You want to ask inputField.text for the user's latest input, instead of searchInput.text.

And I'd recommend renaming searchInput to something like searchDisplayText so you or another developer won't confuse it for an input source in future.

Also, note this was exactly the resolution to the existing Q&A thread I linked you to from two years ago, so don't underestimate your ability to find these answers for yourself by searching.

\$\endgroup\$
  • \$\begingroup\$ Well thanks will take into consideration. I just named var inputField for unitys input field variable and searchInput for the actuall text component since it is the actuall text field. But i agree it is not clear. Thanks \$\endgroup\$ – Lucián Blažek Jul 26 at 12:15
  • \$\begingroup\$ Well also I found that link too but since there is no anwer except mentioning that callback I was left hopeless. \$\endgroup\$ – Lucián Blažek Jul 26 at 12:20
  • \$\begingroup\$ "no answer except mentioning that callback"? Don't forget to scroll all the way to the bottom: "mistake was that I was passing the Text.text value rather than the InputField.text value. Once I changed this it all appears to be working correctly" — that's exactly the case and fix for your issue. \$\endgroup\$ – DMGregory Jul 26 at 12:22
1
\$\begingroup\$

you do not need the extra searchInput you can remove that and switch out to get the text from inputField.text

private void Start()
{
inputField = GetComponent<InputField>();
searchInput = inputField.textComponent;//can remove this line
}
public void Search()
{
  if (searchInput == null)
  {
    Debug.LogWarning("Can't find search field.");
    return;
  }
//TODO: text value is always one letter behind.
string searchVal = inputField.text;//and change this to get value of inputField text instead of textComponent;
Debug.Log("Searching value: " + searchVal);

CraftingManager.instance.RenderSearchedRecipes(searchVal);
}
\$\endgroup\$
  • \$\begingroup\$ Thank you! Will try. Give me a second \$\endgroup\$ – Lucián Blažek Jul 26 at 12:13
  • \$\begingroup\$ Thank you! That was it. The inputField.text is the actual value after character validation that I want. Now it works! Thank you kind sir. \$\endgroup\$ – Lucián Blažek Jul 26 at 12:19
  • \$\begingroup\$ For some reason can not vote your answer as the correct one also. Sorry about that \$\endgroup\$ – Lucián Blažek Jul 26 at 12:23
1
\$\begingroup\$

Another way to achieve this is to make use of dynamic parameters on UnityEvents.

Events that can provide parameters at runtime are marked with those parameters in the inspector (and detailed in the relevant doc pages). e.g. On Value Changed (String) in the inspector shows that this event can provide a string argument - in this case the provided argument is the new value.

An example of writing a handler which could process that:

public void Search(string searchString) {
    CraftingManager.instance.RenderSearchedRecipies(searchString);
}

This negates the need for referencing the input or display components directly, meaning less possibility for confusion. Plus the bonus that it does not need to be part of the same GameObject, if that ever needs to change.

You would assign this handler in the same way as any other - just make sure you select your function from the Dynamic section of the drop-down (otherwise Unity will expect you to provide a parameter in the inspector which will remain the same for each call).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.