Making an input field with personal text validation at runtime

Here, we are going to create another kind of customization, different from the previous recipes. In this case, we have an input field that we want to perform checks on, thus not allowing the player (instead of allowing, as in the previous recipes) to do something. Unity already has some of these controls in the Input Field (Script) component, but in this recipe, you will learn how you can create your personal filters. In this example, we will develop a simple filter in order for you to understand the concept of how filters work. For instance, we want the player to insert an identifier, maybe for the score database, and we don't want his name to start with a number — because in many programming languages, identifiers cannot start with a number. We can perform this check at runtime by developing a script.

This filter is a basic filter, since it is static and it doesn't check the input in a dynamic way. "Dynamic" in this context means having some parametric constrains in the middle that depend on the sentence itself (for example, every number has to be followed by the letter "a"). In this case, we need to use loops and for cycles to perform the check, but how this interacts with our UI is the same for the basic filter. Therefore, you can learn here how to implement personal text validation at runtime inside your UI. However, in the There's more... section of this recipe, you will see that it is possible to find a way to implement the preceding example of dynamic filtering.

Furthermore, the same section describes how we can modify the script to give feedback to the player. This is very important since we need to communicate what the constraints are to the player, if we don't want to frustrate him.

How to do it...

  1. First of all, we need to create our input field by right-clicking on the Hierarchy panel and then going to UI | Input Field. Rename it to myInputField. Of course, we can place it wherever we want.
  2. Select the input field. Then in the Inspector, navigate to Add Component | New Script, name it PersonalTextValidation, and then click on Create and Add.
  3. Now, double-click on the script in order to edit it. Just like every other occasion when we have dealt with the UI, we have to add the using UnityEngine.UI; statement at the beginning of the script, since we are going to use the InputField class. Before the beginning of the class, we can add this line: [RequireComponent(typeof(InputField))] (without the semicolon at the end). Thus, the script requires an InputField component that is attached to the same game object of it.
  4. We need two private variables: one to keep track of the Input Field (Script) component attached to myInputField, and the other to store the old text of the input field, since it could be needed to reverse the player's changes if he violates our validation format. So let's write these lines:
    private InputField inputField;
    private string oldText;
  5. As usual, in the Start() function, we are going to store the initial values for our private variables. First is a reference in inputField, by calling GetComponent<InputField> () function, which takes the Input Field (Script) component attached to the same game object in which this script is placed. Then comes oldText, with the starting text of our input field. So, we have this code:
      inputField = GetComponent<InputField> ();
      oldText = inputField.text;
  6. The next step is to create a new function that will be called every time we want a check in the text. This function only takes one parameter, which is the text that needs to be checked. Therefore, we can add this:
    public void Check (string newText) {
    }
  7. We have created the Check() function; now we have to fill in it. So, let's add the first control through an if statement. We check whether newText is an empty string, and if so, we just assign this new value to oldText and return, since there is nothing to check:
      if(newText == ""){
        oldText = newText;
        return;
      }
  8. The next if statement is the one that really performs our check: no numbers at the beginning of our string. So, as a condition, we verify that the first character is not a number using a chain of OR operators. We retrieve the first character of newText by accessing it as an array, and we are sure that here it contains at least one character; this is because in the previous check, we would have returned if the string was empty. So, we can write the following:
        if(newText[0] == '1'||
           newText[0] == '2'||
           newText[0] == '3'||
           newText[0] == '4'||
           newText[0] == '5'||
           newText[0] == '6'||
           newText[0] == '7'||
           newText[0] == '8'||
           newText[0] == '9'||
           newText[0] == '0'){
  9. Now, if the condition is verified, we have to restore oldText inside the text of inputField, since this newText didn't pass our checks. Otherwise, if the condition is not verified, it means that our string has passed the checks. We have to update oldText with newText in an else statement, so let's continue the code of the previous step with this:
        inputField.text = oldText;
      }else{
        oldText = newText;
      }
  10. Save your script and come back to Unity. The next step is to pass the string that the player is writing to our script, so we need an event that sends it every time the text inside the input field is changed. If we select and then look inside the Input Field (Script) component, we can notice that there are two events. Let's click on the small + sign on the On Value Change (String) event tab in the bottom-right corner.
  11. Drag the script inside the object variable and in the drop-down menu, go to PersonalTextValidation | Check. We also have to ensure that we have selected Check in the first set of functions, called Dynamic string, as shown in the following screenshot (and not Check (string) in the second set, called Static Parameters):
    How to do it...
  12. The final result should look like this:
    How to do it...
  13. Now everything is ready, so we can click on the play button to check whether everything works. Thus, when the player types something in our input field, it cannot start with a number.

How it works...

We started by creating a script in which there is a function that takes the parameter as a string and it checks whether the string starts with a number. If so, it restores the string that was there before to insert the number at the beginning. Otherwise, it doesn't affect the input field. Then, we had to create an event that, every time the string inside the input field changes, it triggers our function by passing to it the string that the player is typing.

There's more...

The following sections help us to improve the text filtering and to understand how the dynamic filtering works so that we can implement our own ones.

Checking the string when the player finished to type

Sometimes, the design of the game requires that the string checking should happen after the player has finished typing it. In such cases, we don't have to perform the check every time that the string changes, but only when the player completes edit that input field. The easiest way to do this is by changing the event in order to trigger our function, only at the end. We need to change what we did in step 11 Instead of adding an event to the On Value Change (String) tab, we have to create a new one on the End Edit (String) event tab by clicking on the + sign in the bottom-right corner. So finally, we should have something that looks like this:

Checking the string when the player finished to type

Our function is called only when the player finishes editing the input field. However, keep in mind that in this way, if the string typed is invalid, the last valid string will be restored — the one that was present before, at the beginning of the last edit session. Giving feedback to the player on why the string he is writing is not acceptable for this input field is important.

It may be confusing for the player when he cannot insert some characters at certain points, for example, inserting numbers at the beginning. Thus, in some way, we should give feedback to the player to make him understand why he cannot use some strings or to indicate what has gone wrong.

To do this, we have to use another Text (Script) component and handle it inside our script. Thus, let's change our script.

First, we need three public variables. The first one is for storing the reference to the Text (Script) component, and the other two are for customizing it. The second is for the error string to place on it, and the third is for changing its color. We can write the following lines:

public Text feedbackText;
public string errorString;
public Color newColor;

However, we also need two private variables to store the original values of feedbackText, like this:

private string originalFeedbackText;
private Color originalFeedbackColor;

These variables need to be assigned in the Start() function by adding the following two lines at the bottom of the function:

  originalFeedbackText = feedbackText.text;
  originalFeedbackColor = feedbackText.color;

Now, we should go through the Check() function inside the then branch, which is inside the if statement. Then we can assign the new parameters, the text and the color, to feedbackText in this way:

    feedbackText.text = errorString;
    feedbackText.color = newColor;

Next, restore the originals in the else branch by adding these lines:

     feedbackText.text = originalFeedbackText;
    feedbackText.color = originalFeedbackColor;

After saving the script, we are able to assign a Text (Script) to the Feedback Text component, along with the text (which can be The string cannot start with a number) and a color (which can be red).

Tip

We can create another UI text to assign to Feedback Text. In this case, we may create an interesting variation, since this checking is at the beginning of our script. We can assign to it Placeholder, which is one of the children of myInputField. It is the text that there is inside the input field when it is empty.

So, if the player tries to insert a number at the beginning, we should get something like this:

Checking the string when the player finished to type

Using for cycles for dynamic filtering

In this section, we will present some basic notions on how a dynamic filter can be executed using for cycles. We will see that the concept is the same as that which we've used so far. In the introduction, we made the following example: every number has to be followed by the letter "a." In this case, what we need is looping over the string, and every time we find a number, it must be followed by the letter "a." Otherwise, the filter will restore the old string that the player was writing.

The first part of the check() function is the same:

if(newText == ""){
  oldText = newText;
  return;
}

In fact, we always want to check whether the new string is empty. If it is, we return so that we don't waste time in performing a check on an empty string.

Tip

In some cases, the input field may require at least a single character. In this case, we can check whether the string is empty, and if so, we reverse the modifications that are done to the string.

Now we will create a bool variable to determine whether we have a number, from one cycle to the next. To do this, we need to write the following:

bool mustFollowA = false;

Finally, the for cycle will go through all the characters of the string. If we find a number, we set our mustFollowA variable to true. By doing this, we know that before the next cycle, there was a number. Of course, if we find another number, we can still keep iterating, since the new digit is part of the same number. For example, suppose we have a string bc12a. When the cycle reaches the number 2, it knows that before 2 there was a number, 1 in this case. However, the letter a must follow any number, and 12 is a number. Then, if we find an a, in lowercase or uppercase, we don't need to be concerned with what was there before. So, we can just deactivate the constraint by setting the mustFollowA variable to false. Otherwise, if the character is neither a number nor a, we check whether the mustFollowA variable is true. If so, it means that our test has failed. Hence, we restore the old string and return. Then, if the for cycle terminates, the test doesn't fail. Thus, we can assign the new string to our oldText variable:

  for(int i=0; i < newText.Length; i++){
    if(newText[i] == '1'||
       newText[i] == '2'||
       newText[i] == '3'||
       newText[i] == '4'||
       newText[i] == '5'||
       newText[i] == '6'||
       newText[i] == '7'||
       newText[i] == '8'||
       newText[i] == '9'||
       newText[i] == '0'){
       mustFollowA = true;
      continue;
    }else if(newText[i] == 'a'||
             newText[i] == 'A'){
      mustFollowA = false;
      continue;
    }
    if(mustFollowA = true){ //FAIL: There is a number followed by another letter
      inputField.text = oldText;
      return;
    }
  }
  oldText = newText;

See also

  • If you want to put a lower bound limit for characters, it is worthwhile taking a look at the next recipe, Making an input field for password with a lower bound limit for characters.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.133.233