# Only 1 TextMeshProUGUI being affected by coroutine

I have a prefab m_wordContainer which is empty other than having a TextMeshProUGUI as a child (I did this so that I could position this container freely not being bugged by an animation played by the TMPUGUI object). At the start of the program I start a coroutine (SpawnWordPopups) which splits the words in a sentence, making a copy of m_wordContainer and assigning that word to the text property of its TMPUGUI, spawning such m_wordContainer in a random location within the screen, and then starting a coroutine (FadeText) that fades in the text of every TMPUGUI. The problem is that only one of the TMPUGUI has its text faded, even though the FadeText coroutine is called seemingly correctly. All words are shown as expected, only thing missing is the fading effect on all but the first word that fades. If I called FadeText like this: if (i > 0) { yield return FadeText(true, tmpText, 2); } then only the second word will be faded.

 [SerializeField] private GameObject m_wordContainer;

void Start()
{
yield return StartCoroutine(SpawnWordPopups("test foo bar"));
}

private IEnumerator SpawnWordPopups(string l_line)
{
string[] words = l_line.Split(' ');
List<Vector3> wordPositions = new List<Vector3>();
for (int i = 0; i < words.Length; ++i)
{
Vector3 spawnLocation = new Vector3(Random.Range(m_wordScreenDistanceOffset, Screen.width - m_wordScreenDistanceOffset), Random.Range(m_wordScreenDistanceOffset, Screen.height - m_wordScreenDistanceOffset), 0);
if (IsWordOverlapping(wordPositions, spawnLocation))
{
--i;
continue;
}
GameObject wordContainer = Instantiate(m_wordContainer, transform.parent);
wordContainer.transform.position = spawnLocation;
TextMeshProUGUI tmpText = wordContainer.GetComponentInChildren<TextMeshProUGUI>();
tmpText.text = words[i];

}
}

{
float time = Time.time;
float until = Time.time + l_time;
int alphaFrom = l_fadeIn ? 0 : 1;
int alphaGoal = l_fadeIn ? 1 : 0;
Color textColor = l_textBox.color;
textColor.a = l_fadeIn ? 0 : 1;
l_textBox.color = textColor;

while (time < until)
{
textColor = l_textBox.color;
textColor.a = Mathf.Lerp(alphaFrom, alphaGoal, Time.time / l_time);
l_textBox.color = textColor;
time += Time.deltaTime;
yield return null;
}
textColor.a = l_fadeIn ? 1 : 0;
l_textBox.color = textColor;
}


Could anyone shed some light into this issue I'm having? Why are not all the words being faded?

• It's more of a preference thing, but standard convention for C# is not to apply scope prefixes like m_ and l_ to your variable names. A good modern IDE should eliminate the need for these prefixes, and they make typing a lot more of a hassle due to the awkward placement of the underscore on most keyboards. Aug 14 '20 at 0:07

I think the problem is the equation you're using for the t argument of Mathf.Lerp:

Time.time / l_time


Let's say your game has been running for 10 seconds. Then Time.time is 10, but l_time is 2, so your t is 10 / 2 = 5 which gets clamped to 1. What you should have written is (Time.time - time) / startTime. Your time-tracking solution is also messy in general. Here's the whole function with additional improvements:

private IEnumerator FadeText(bool l_fadeIn, TextMeshProUGUI l_textBox, float l_duration)
{
float start = Time.time; //clearer name
float until = start  + l_duration;
int alphaFrom = l_fadeIn ? 0 : 1;
int alphaGoal = 1 - alphaFrom;
Color textColor = l_textBox.color;
//removed redundant code here

while (Time.time < until) //simplified
{ //don't need to keep reading the color from the text field each frame
textColor.a = Mathf.Lerp(alphaFrom, alphaGoal, (Time.time - start) / l_duration);
l_textBox.color = textColor;
yield return null;
}
textColor.a = alphaGoal; //no need to recalculate the value
l_textBox.color = textColor;
}

• That was it, thank you so much! A lot of redundant lines were added in desperation trying to find the issue but never even thought about that equation that way, silly of me. Cheers! Aug 14 '20 at 19:48
• @aramos Great, glad to help! Aug 14 '20 at 20:05