I’m making a typing game that pulls lines from a text file, adds them to a string array and displays as many as it can fit in a text box. When all lines that currently fit are typed, they are removed from the list and the text box and replaced with the next set of lines that can fit. The text box right now will add lines to the text box until a line would be added that would make the text overflow. Since some lines are longer than the entire length of the text box I want the system to remove only the text that would overflow, not the entire line.
My entire script for the game is listed below. Right now the script tries to add lines to the text box but if the line would cause overflow it does not add the line and stops trying to add more until the Update Text Display is called again. I tried many ways to find all the text that overflows and somehow put it in a new string to be added next in line in the allLines list but after hours I have given up. I would really appreciate help in making it so that any text that would cause overflow is not displayed but the rest of the line that can fit still would.
using UnityEngine;
using TMPro;
using System.Collections.Generic;
public class TypingGameManager : MonoBehaviour
{
// Reference to the TextMeshProUGUI component
public TextMeshProUGUI textMeshPro;
// Name of the text file in the Resources folder (without extension)
public string fileName = "YourTextFile";
// Color for typed characters
public Color32 typedColor = new Color32(0, 255, 0, 255); // Green color
public List<string> allLines;
public int currentLineIndex = 0;
public int currentCharIndex = 0;
public int linesDisplayed = 0;
public int linesShown;
// Typewriter audio components
public AudioClip typingSound;
public AudioSource audioSource;
void Start()
{
// Load the text asset from the Resources folder
TextAsset textAsset = Resources.Load<TextAsset>(fileName);
// Check if the text asset was found
if (textAsset != null)
{
// Split the text into lines
allLines = new List<string>(textAsset.text.Split(new[] { 'r', 'n' }, System.StringSplitOptions.RemoveEmptyEntries));
// Set TextMeshPro overflow mode to truncate
textMeshPro.overflowMode = TextOverflowModes.Truncate;
// Display the first batch of lines in the TextMeshPro component
UpdateTextDisplay();
}
else
{
Debug.LogError("File not found in Resources: " + fileName);
}
// Set the typing sound
audioSource.clip = typingSound;
}
void Update()
{
if (currentLineIndex < allLines.Count)
{
if (currentCharIndex < allLines[currentLineIndex].Length)
{
// Check if a key was pressed
if (Input.anyKeyDown)
{
// Get the pressed key
string input = Input.inputString;
if (input.Length > 0)
{
char typedChar = input[0];
// Check if the typed character matches the current character in the line
if (typedChar == allLines[currentLineIndex][currentCharIndex])
{
audioSource.Play();
// Move to the next character
currentCharIndex++;
// Update the display
UpdateTextDisplay();
}
}
}
}
else
{
// Move to the next line or refill if all characters in the current lines have been typed
if (currentLineIndex + 1 < allLines.Count)
{
currentLineIndex++;
currentCharIndex = 0;
UpdateTextDisplay();
}
if (currentLineIndex == linesShown)
{
// If all lines have been typed, refill the text box with new lines
RefillTextBox();
}
}
}
}
void UpdateTextDisplay()
{
// Combine all lines into a single string with typed characters colored
string displayedText = "";
string testText = "";
linesShown = 0;
for (int i = 0; i < allLines.Count; i++)
{
if (i >= linesDisplayed)
{
if (i == currentLineIndex)
{
// Separate the typed part and the remaining part of the current line
string typedText = allLines[i].Substring(0, currentCharIndex);
string remainingText = allLines[i].Substring(currentCharIndex);
// Create a colored string for the typed part
string coloredTypedText = $"<color=#{ColorUtility.ToHtmlStringRGBA(typedColor)}>{typedText}</color>";
// Append the current line with colored typed text
testText += coloredTypedText + remainingText;
}
else if (i < currentLineIndex)
{
// Previous lines, fully typed
testText += $"<color=#{ColorUtility.ToHtmlStringRGBA(typedColor)}>{allLines[i]}</color>";
}
else
{
// Future lines, not yet typed
testText += allLines[i];
}
// Add a newline character between lines
if (i < allLines.Count - 1)
{
testText += "n";
}
// Temporarily set text to calculate height
textMeshPro.text = testText;
textMeshPro.ForceMeshUpdate();
// Check if text overflows
if (textMeshPro.isTextOverflowing)
{
break;
}
else
{
displayedText = testText;
linesShown++;
}
}
}
// Update the TextMeshPro text
textMeshPro.text = displayedText;
}
int CalculateLinesToFit()
{
float textHeight = textMeshPro.rectTransform.rect.height;
TMP_TextInfo textInfo = textMeshPro.GetTextInfo("A");
float lineHeight = textInfo.lineInfo[0].lineHeight;
int linesToFit = (int)(textHeight / lineHeight);
return linesToFit;
}
void RefillTextBox()
{
Debug.Log("To Refill");
// Clear the current text
textMeshPro.text = "";
// Reset line and character indices
currentLineIndex = 0;
currentCharIndex = 0;
// linesDisplayed = 0;
// Remove typed lines from the list
allLines.RemoveRange(0, linesShown);
// Display the next batch of lines in the TextMeshPro component
UpdateTextDisplay();
}
}
Luke Piazza is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.