- Home /
Yet another problem... Textbox typewriter, C#
Hi, I'm having another problem , it's not an error, but I wan't text to display on a text box like a type writer, and the result I get is it immediately shows all text at once and has random letters appear at the end. It looks like this:
and the last letter keeps changing multiple times each for every sentence that is said.
Here are my three scripts that tie into the text box:
TextImporter
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TextImporter : MonoBehaviour {
public TextAsset textFile;
public string[] textLines;
// Use this for initialization
void Start () {
if (textFile != null) {
textLines = (textFile.text.Split('\n'));
}
}
}
ActivateTextAtLine
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ActivateTextAtLine : MonoBehaviour {
public TextAsset theText;
public int startLine;
public int endLine;
public TextBoxManager theTextBox;
public bool requireButtonPress;
private bool waitForPress;
public bool destroyWhenActivated;
// Use this for initialization
void Start () {
theTextBox = FindObjectOfType<TextBoxManager> ();
}
// Update is called once per frame
void Update () {
if (waitForPress && Input.GetKeyDown (KeyCode.J)) {
theTextBox.ReloadScript (theText);
theTextBox.currentLine = startLine;
theTextBox.endAtLine = endLine;
theTextBox.EnableTextBox ();
if (destroyWhenActivated) {
Destroy(gameObject);
}
}
}
void OnTriggerEnter2D(Collider2D other) {
if (other.name == "Player") {
if (requireButtonPress) {
waitForPress = true;
return;
}
theTextBox.ReloadScript (theText);
theTextBox.currentLine = startLine;
theTextBox.endAtLine = endLine;
theTextBox.EnableTextBox ();
theTextBox.isActive = true;
if (destroyWhenActivated) {
Destroy(gameObject);
}
}
}
void OnTriggerExit2D(Collider2D other)
{
if (other.name == "Player") {
waitForPress = false;
}
}
}
TextBoxManager
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class TextBoxManager : MonoBehaviour
{
public GameObject textBox;
public Text theText;
public TextAsset textFile;
public string[] textLines;
public int currentLine;
public int endAtLine;
public playerController player;
public bool isActive;
public bool stopPlayerMovement;
private bool isTyping = false;
private bool cancelTyping = false;
public float typeSpeed;
// Use this for initialization
void Start()
{
player = FindObjectOfType<playerController>();
if (textFile != null)
{
textLines = (textFile.text.Split('\n'));
}
if (endAtLine == 0)
{
endAtLine = textLines.Length - 1;
}
if (isActive)
{
EnableTextBox();
}
else
{
DisableTextBox();
}
}
void Update()
{
if (!isActive)
{
return;
}
theText.text = textLines [currentLine];
if (Input.GetKeyDown(KeyCode.Return))
{
if (!isTyping)
{
currentLine += 1;
if (currentLine > endAtLine)
{
DisableTextBox();
}
else
{
StartCoroutine(TextScroll(textLines[currentLine]));
}
}
else if (isTyping && !cancelTyping)
{
cancelTyping = true;
}
}
}
private IEnumerator TextScroll(string lineOfText)
{
int letter = 0;
theText.text = "";
isTyping = true;
cancelTyping = false;
while (isTyping && !cancelTyping && (letter < lineOfText.Length - 1))
{
theText.text += lineOfText[letter];
letter += 1;
yield return new WaitForSeconds(typeSpeed);
}
theText.text = lineOfText;
isTyping = false;
cancelTyping = false;
}
public void EnableTextBox()
{
textBox.SetActive(true);
isActive = true;
if (stopPlayerMovement)
{
player.canMove = false;
player.anim.speed = 0;
}
StartCoroutine(TextScroll(textLines[currentLine]));
}
public void DisableTextBox()
{
textBox.SetActive(false);
isActive = false;
player.canMove = true;
}
public void ReloadScript(TextAsset theText)
{
if (theText != null)
{
textLines = new string[1];
textLines = (theText.text.Split('\n'));
}
}
}
Here are the parameters:
$$anonymous$$ind showing the text file? I think I could better help if I saw it.
@Ejpj123 So is that a no? I kind of wanted to see if I can help but it is ok if you figured it out.
@$$anonymous$$ittenSnipes Here it is: " 1. Hey there! 2. Who are you? 3. ... 4. ... 5. ... 6. Oh, the strong silent type huh? 7. That's okay, I guess... " The quotation marks are not part of it.
Ignore the Type Speed. I was just testing out something and that is not what is causing the problem.
could you create a test case with just the code relevant? just showing how you activate your text. 160 lines of code is a little long.
I agree but I feel all the code is relevant because I am not sure what part of the code is relevant.
narrow it down. maybe just run your Coroutine from Start just once with a certain text. If you press play, it should run it and you'll see if it works or skips to the end. either way you know where to look. even better, use break points and watch your code executing.
I'd just do something like this to be honest...
public float delay;
private int current;
public Text text;
private string currentText;
private StringBuilder builder = new StringBuilder();
private bool writing;
void DisplayText(string s)
{
if (!writing)
{
writing = true;
currentText = s;
current = 0;
builder.Append(currentText [current]);
text.text = builder.ToString();
Invoke("IterateText", delay);
}
}
void IterateText()
{
if (current +1 < currentText.Length)
{
current++;
builder.Append(currentText[current]);
text.text = builder.ToString();
Invoke("IterateText", delay);
}
else
{
builder.Length = 0;
writing = false;
}
}
$$anonymous$$aybe I'm misunderstanding the situation though... As far as multiple lines goes, you could just use a content size fitter on the Text object so it auto-expands. Then it will automatically move down lines. Or you could always use a line identifier like "_".
@RobAnthem $$anonymous$$ultiple lines is not the problem. The problem is my text won't display out letter by letter, ins$$anonymous$$d the whole line of text just display's at once. And each time the next set of text is displayed, all the letters in that line display at the end of the line, per the photo at the top.
$$anonymous$$y suggestion: Re-write the solution. This is just a convoluted mess, and it doesn't need to be. You're altering the same variables in multiple sections, and all in all, its just unnecessary. You know what you want to accomplish, so just create the simplest function to do so. If you're already using the Update loop, then I suggest NOT using coroutines, you're just creating issues for yourself. I already wrote an example solution of displaying each character in succession, but you obviously don't want that. You can accomplish what you want in a fraction of the code you have, and I'd suggest doing so. I was going to tell you how to fix your current code, but I don't think it's worth fixing.
Also, don't use GameObject.Find("name")
, it's a terrible, useless function that only exists for laziness. Do Singleton, or find the object by its type, but iterating every object in your scene and checking its name is a horrible way to go, and names aren't even reliable, it's like searching for someone based on the clothes they are wearing.
Answer by domportera · Mar 26, 2018 at 06:12 PM
I'm not sure about that last character you're dealing with, but this could help you reveal text one letter at a time https://answers.unity.com/questions/219281/making-text-boxes-with-letters-appearing-one-at-a.html