This is a little dated, but I found this “Screen Printer” script here a few years back (courtesy of @JoeStrout I believe). It uses the old GUIText component, which is legacy now, but it would be easy enough to convert into using the new UI canvas system. Just make a new GameObject in your scene called “Screen Printer” and attach this script to it, and you can call it using the static function ScreenPrinter.Print(“text here”); to add text to the screen.
The real reason why I’m sharing this is as an example though- it shows you exactly how you should approach this problem. Store each of the string “messages” as items in a list. “New messages” have their own list, which when updated will bump old messages off of the “message history”, add its own messages, and then clear itself. Every time that happens, the Text component is updated by dumping the whole current message history into it. In other words, you NEVER have to directly manipulate strings the way that you’re doing, because they’re always stored in a list. The text that goes into the Text component never comes back out again to be “processed”, it just gets overwritten completely the next time a message update occurs. Get it? 
using UnityEngine;
using System.Collections.Generic;
[RequireComponent(typeof(GUIText))]
public class ScreenPrinter : MonoBehaviour
{
public TextAnchor anchorAt = TextAnchor.LowerLeft;
public int numberOfLines = 5;
public int pixelOffset = 5;
static ScreenPrinter defaultPrinter = null;
static bool quitting = false;
GUIText guiText;
List<string> newMessages = new List<string>();
TextAnchor _anchorAt;
float _pixelOffset;
List<string> messageHistory = new List<string>();
// static Print method: finds a ScreenPrinter in the project,
// or creates one if necessary, and prints to that.
public static void Print(object message)
{
if (quitting) return; // don't try to print while quitting
if (!defaultPrinter)
{
GameObject gob = GameObject.Find("Screen Printer");
if (!gob) gob = new GameObject("Screen Printer");
defaultPrinter = gob.GetComponent<ScreenPrinter>();
if (!defaultPrinter) defaultPrinter = gob.AddComponent<ScreenPrinter>();
}
defaultPrinter.LocalPrint(message);
}
// member LocalPrint method: prints to this particular screen printer.
public void LocalPrint(object message)
{
if (quitting) return; // don't try to print while quiting
newMessages.Add(message.ToString());
}
void Awake()
{
guiText = GetComponent<GUIText>();
if (!guiText)
{
guiText = gameObject.AddComponent<GUIText>();
transform.position = Vector3.zero;
transform.localScale = new Vector3(0, 0, 1);
}
_anchorAt = anchorAt;
UpdatePosition();
}
void OnApplicationQuitting()
{
quitting = true;
}
void Update()
{
// if anchorAt or pixelOffset has changed while running, update the text position
if (_anchorAt != anchorAt || _pixelOffset != pixelOffset)
{
_anchorAt = anchorAt;
_pixelOffset = pixelOffset;
UpdatePosition();
}
// if the message has changed, update the display
if (newMessages.Count > 0)
{
for (int messageIndex = 0; messageIndex < newMessages.Count; messageIndex++)
{
messageHistory.Add(newMessages[messageIndex]);
}
if (messageHistory.Count > numberOfLines)
{
messageHistory.RemoveRange(0, messageHistory.Count - numberOfLines);
}
// create the multi-line text to display
guiText.text = string.Join("\n", messageHistory.ToArray());
newMessages.Clear();
}
}
void UpdatePosition()
{
switch (anchorAt)
{
case TextAnchor.UpperLeft:
transform.position = new Vector3(0.0f, 1.0f, 0.0f);
guiText.anchor = anchorAt;
guiText.alignment = TextAlignment.Left;
guiText.pixelOffset = new Vector2(pixelOffset, -pixelOffset);
break;
case TextAnchor.UpperCenter:
transform.position = new Vector3(0.5f, 1.0f, 0.0f);
guiText.anchor = anchorAt;
guiText.alignment = TextAlignment.Center;
guiText.pixelOffset = new Vector2(0, -pixelOffset);
break;
case TextAnchor.UpperRight:
transform.position = new Vector3(1.0f, 1.0f, 0.0f);
guiText.anchor = anchorAt;
guiText.alignment = TextAlignment.Right;
guiText.pixelOffset = new Vector2(-pixelOffset, -pixelOffset);
break;
case TextAnchor.MiddleLeft:
transform.position = new Vector3(0.0f, 0.5f, 0.0f);
guiText.anchor = anchorAt;
guiText.alignment = TextAlignment.Left;
guiText.pixelOffset = new Vector2(pixelOffset, 0.0f);
break;
case TextAnchor.MiddleCenter:
transform.position = new Vector3(0.5f, 0.5f, 0.0f);
guiText.anchor = anchorAt;
guiText.alignment = TextAlignment.Center;
guiText.pixelOffset = new Vector2(0, 0);
break;
case TextAnchor.MiddleRight:
transform.position = new Vector3(1.0f, 0.5f, 0.0f);
guiText.anchor = anchorAt;
guiText.alignment = TextAlignment.Right;
guiText.pixelOffset = new Vector2(-pixelOffset, 0.0f);
break;
case TextAnchor.LowerLeft:
transform.position = new Vector3(0.0f, 0.0f, 0.0f);
guiText.anchor = anchorAt;
guiText.alignment = TextAlignment.Left;
guiText.pixelOffset = new Vector2(pixelOffset, pixelOffset);
break;
case TextAnchor.LowerCenter:
transform.position = new Vector3(0.5f, 0.0f, 0.0f);
guiText.anchor = anchorAt;
guiText.alignment = TextAlignment.Center;
guiText.pixelOffset = new Vector2(0, pixelOffset);
break;
case TextAnchor.LowerRight:
transform.position = new Vector3(1.0f, 0.0f, 0.0f);
guiText.anchor = anchorAt;
guiText.alignment = TextAlignment.Right;
guiText.pixelOffset = new Vector2(-pixelOffset, pixelOffset);
break;
}
}
}