Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

String Hell

Discussion in 'Scripting' started by ShottyMonsta, Jul 11, 2014.

  1. ShottyMonsta

    ShottyMonsta

    Joined:
    May 23, 2014
    Posts:
    25
    Introduction:

    I have the following script, the aim of it is to allow the user to input into a string, whenever a line of the string is longer than 34 characters it will drop onto a new line.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class freeformWriting : MonoBehaviour {
    5.     string userInput = "";
    6.     int numberOfLines = 1;
    7.  
    8.     // Use this for initialization
    9.     void Start () {
    10.         this.GetComponent<TextMesh> ().text = userInput;
    11.     }
    12.  
    13.     // Update is called once per frame
    14.     void Update () {
    15.         userInput += Input.inputString;
    16.  
    17.         if (Input.GetKey (KeyCode.Backspace)) {
    18.             userInput = userInput.Substring (0, userInput.Length-1);
    19.             userInput.ToString();
    20.         }
    21.  
    22.         if (Input.GetKeyDown (KeyCode.Return)) {
    23.             userInput += "\n";
    24.         }
    25.  
    26.         for (int i = userInput.Length; i >= 1; i--)     {
    27.             if (i % (34 * numberOfLines) == 0) {
    28.                 userInput = userInput.Insert (i, "-\n");
    29.                 numberOfLines += 1;
    30.             }
    31.         }
    32.  
    33.         this.GetComponent<TextMesh> ().text = userInput;
    34.     }
    35. }
    36.  


    PROBLEM 1:


    Code (CSharp):
    1.         if (Input.GetKeyDown (KeyCode.Backspace)) {
    2.             userInput = userInput.Substring (0, userInput.Length-1);
    3.         }
    This only lets you delete the last character typed. To be able to delete another character the user must enter another character. I want it so the user can keep deleting characters.

    I've tried using "Input.GetKey (KeyCode.Backspace)" but this means the encapsulated code will trigger at the keyboard refresh rate and, although it allows the user to delete multiple characters it is way too fast.

    Is it something to do with "string = string.Substring (0, string.length-1)"? I tried "string.remove (string.length-1, 1)" but that didn't allow the user to delete any characters at all...



    PROBLEM 2:

    The following bit of code is supposed to iterate through all characters in the string, if the characters index is divisible by 34 * numberOfLInes then insert a new line and increment numberOfLines by 1. The purpose of this is to generate a new line when the text becomes longer than the screen (like a word processor).

    Code (CSharp):
    1. for (int i = userInput.Length; i >= 1; i--)     {
    2.             if (i % (34 * numberOfLines) == 0) {
    3.                 userInput = userInput.Insert (i, "-\n");
    4.                 numberOfLines += 1;
    5.             }
    6.         }
    This code works fine, until you start deleting characters, then it's like the indexes of the string get messed up so the string goes of the screen before start a new line.
     
  2. ShottyMonsta

    ShottyMonsta

    Joined:
    May 23, 2014
    Posts:
    25
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    I believe the problem here is that you are first appending Input.inputString, then processing backspace and return. According to the docs, Input.inputString can contain \b and \n. I recommend moving the appending of inputString to an "else" statement after the special character handling; in addition, you should probably compare with inputString rather than GetKeyDown (that is, Input.inputString == "\b") just to make sure everything is consistent.

    I bet you that pressing return is also inserting double-spaces for the same reason.
     
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    As for the second problem, I actually recommend not modifying the user's inputted string itself in this way, and instead doing so only when you display the string. And you should write it so that it splits the string on word breaks, rather than simply at 34 characters.

    Since it's easier than debugging someone else's code, here's my own word wrap function, have at it:
    Code (csharp):
    1.  
    2.     public static string WrapText(string input, int characterWrap, int maxLines = 999) {
    3.  
    4.         if (maxLines <= 0) return "";
    5.  
    6.         string[] words = input.Split(new string[]{" "},StringSplitOptions.None);
    7.  
    8.         string outputBuilder = "";
    9.  
    10.         int currentWidth = 0;
    11.  
    12.         int currentLine = 0;
    13.  
    14.         foreach (string w in words) {
    15.  
    16.             outputBuilder += w + " ";
    17.  
    18.             currentWidth += w.Length + 1;
    19.  
    20.             if (currentWidth > characterWrap) {
    21.  
    22.                 currentWidth = 0;
    23.  
    24.                 outputBuilder += "\n";
    25.  
    26.                 currentLine++;
    27.  
    28.             }
    29.  
    30.             if (currentLine >= maxLines) break;
    31.  
    32.         }
    33.  
    34.         return outputBuilder;
    35.  
    36.     }
    37.  
     
    ShottyMonsta likes this.
  5. ShottyMonsta

    ShottyMonsta

    Joined:
    May 23, 2014
    Posts:
    25

    You are legend!

     
  6. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    Modifying strings inside an update function is GC heaven. strings are immutable, meaning when you "change" the string to something else, it will basically create a new string and copy the contents into it.

    This is where you should use stringbuilder.
     
  7. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    Yeah, it could certainly be optimized I suppose. If you're refreshing the paragraph every frame it's certainly worth doing...