IEnumerator TextJitter() { List <TMP_WordInfo> wInfo; wInfo = new List <TMP_WordInfo>(); int[] wordsToJitter; wordsToJitter = null; if (jitterWords != null) { wordsToJitter = jitterWords.ToArray(); } else { wordsToJitter = textFX[sentenceCount].jitterIndexes; } while (true) { if (sentenceCount < textFX.Length) { if (textFX[sentenceCount].wordColors.keyWords.Length != 0) { SetTextColor(keyColor, textFX[sentenceCount].wordColors.keyWords); } else if (textFX[sentenceCount].wordColors.characterWords.Length != 0) { SetTextColor(characterColor, textFX[sentenceCount].wordColors.characterWords); } else if (textFX[sentenceCount].wordColors.redWords.Length != 0) { SetTextColor(redColor, textFX[sentenceCount].wordColors.redWords); } else if (textFX[sentenceCount].wordColors.mechanicWords.Length != 0) { SetTextColor(mechanicColor, textFX[sentenceCount].wordColors.mechanicWords); } else { dialogueText.ForceMeshUpdate(true); } } wInfo.Clear(); foreach (int wordIndex in wordsToJitter) { //Add each word's wordInfo wInfo.Add(dialogueText.textInfo.wordInfo[wordIndex]); } Matrix4x4 matrix; int loopCount = 0; hasTextChanged = true; List <TMP_MeshInfo[]> cachedMeshInfo; cachedMeshInfo = new List <TMP_MeshInfo[]>(); cachedMeshInfo.Clear(); foreach (TMP_WordInfo wordInfo in wInfo) { cachedMeshInfo.Add(wordInfo.textComponent.textInfo.CopyMeshInfoVertexData()); } if (hasTextChanged) { foreach (TMP_WordInfo wordInfo in wInfo) { cachedMeshInfo.Add(wordInfo.textComponent.textInfo.CopyMeshInfoVertexData()); } hasTextChanged = false; } foreach (TMP_WordInfo info in wInfo) { foreach (TMP_MeshInfo[] cMI in cachedMeshInfo) { int characterCount = info.characterCount; if (characterCount == 0) { yield return(new WaitForSeconds(0.25f)); continue; } for (int i = 0; i < characterCount; i++) { int charIndex = info.firstCharacterIndex + i; TMP_CharacterInfo charInfo = dialogueText.textInfo.characterInfo[charIndex]; if (!charInfo.isVisible) { continue; } VertexAnim vertAnim = vertexAnim[charIndex]; int materialIndex = dialogueText.textInfo.characterInfo[charIndex].materialReferenceIndex; int vertexIndex = dialogueText.textInfo.characterInfo[charIndex].vertexIndex; Vector3[] sourceVertices = cMI[materialIndex].vertices; Vector2 charMidBasline = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2; Vector3 offset = charMidBasline; Vector3[] destinationVertices = dialogueText.textInfo.meshInfo[materialIndex].vertices; destinationVertices[vertexIndex + 0] = sourceVertices[vertexIndex + 0] - offset; destinationVertices[vertexIndex + 1] = sourceVertices[vertexIndex + 1] - offset; destinationVertices[vertexIndex + 2] = sourceVertices[vertexIndex + 2] - offset; destinationVertices[vertexIndex + 3] = sourceVertices[vertexIndex + 3] - offset; vertAnim.angle = Mathf.SmoothStep(-vertAnim.angleRange, vertAnim.angleRange, Mathf.PingPong(loopCount / 25f * vertAnim.speed, 1f)); Vector3 jitterOffset = new Vector3(Random.Range(-.25f, .25f), Random.Range(-.25f, .25f), 0); matrix = Matrix4x4.TRS(jitterOffset * CurveScale, Quaternion.Euler(0, 0, Random.Range(-5f, 5f) * AngleMultiplier), Vector3.one); destinationVertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 0]); destinationVertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 1]); destinationVertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 2]); destinationVertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 3]); destinationVertices[vertexIndex + 0] += offset; destinationVertices[vertexIndex + 1] += offset; destinationVertices[vertexIndex + 2] += offset; destinationVertices[vertexIndex + 3] += offset; vertexAnim[i] = vertAnim; } } } for (int i = 0; i < dialogueText.textInfo.meshInfo.Length; i++) { dialogueText.textInfo.meshInfo[i].mesh.vertices = dialogueText.textInfo.meshInfo[i].vertices; dialogueText.UpdateGeometry(dialogueText.textInfo.meshInfo[i].mesh, i); } loopCount += 1; yield return(new WaitForSeconds(0.1f)); } }