IEnumerator BuildText() { int runsThisFrame = 0; string[] textArray = hasMarkup ? MarkupManager.SplitByTag(targetText) : new string[1] { targetText }; // If this is additive text, make sure we include the previous text. _currentText = previousText; // We need a storage variable to separate out the nested text. string nestedText = ""; // aka curText // Build the text by moving through each part for (int i = 0; i < textArray.Length; i++) { string section = textArray[i]; // Tags will always be odd-indexed. Even if there are two in a row, there will be an empty array between them. bool isOdd = i % 2 == 1; if (isOdd && hasMarkup) { // store the current text into something that can be referenced as a restart point as tagged sections of text get added or removed. nestedText = _currentText; NESTED_TEXT childNode = new NESTED_TEXT($"<{section}>", textArray, i); while (!childNode.isDone) { //during each loop we need to call the next step in the markup process // First set a boolean to indicate if a step was taken bool stepped = childNode.Step(); _currentText = nestedText + childNode.displayText; // Only yield if a step was taken in building the string if (stepped) { runsThisFrame++; int maxRunsPerFrame = skip ? 5 : charactersPerFrame; // Handles fast forwarding // Move the variable declaration up? if (runsThisFrame == maxRunsPerFrame) { runsThisFrame = 0; yield return(new WaitForSeconds(skip ? 0.01f : 0.01f * renderSpeed)); } } } i = childNode.arrayProgress + 1; } else // Not processing markup { for (int j = 0; j < section.Length; j++) { _currentText += section[j]; runsThisFrame++; int maxRunsPerFrame = skip ? 5 : charactersPerFrame; // Handles fast forwarding // Move the variable declaration up? if (runsThisFrame == maxRunsPerFrame) { runsThisFrame = 0; yield return(new WaitForSeconds(skip ? 0.01f : 0.01f * renderSpeed)); } } } } // Signal the end of the build process buildProcess = null; }