Add : Shifting subtitles

This commit is contained in:
Jahnisse
2026-05-29 11:57:16 +02:00
parent 137030af6e
commit 334e688277
33 changed files with 13683 additions and 9 deletions
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d7143660499bb5d469a97039fd227086
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,197 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
namespace Unheimlich.UI
{
[RequireComponent(typeof(TextMeshProUGUI))]
public class PerLetterFontShifter : MonoBehaviour
{
#region Serialized Fields
[Header("Fonts")]
[SerializeField] private TMP_FontAsset[] _fonts;
[Header("Timing")]
[SerializeField] private float _shiftInterval = 3f;
[SerializeField] private float _minLetterDelay = 0.05f;
[SerializeField] private float _maxLetterDelay = 0.25f;
[Header("Style")]
[SerializeField] private float _fontSize = 36f;
[SerializeField] private Color _textColor = Color.white;
#endregion
#region Private Fields
private TextMeshProUGUI _originalTmp;
private string _originalText;
private readonly List<TextMeshProUGUI> _letterObjects = new List<TextMeshProUGUI>();
private Coroutine _shiftLoopRoutineHandle;
#endregion
#region Unity Lifecycle Methods
private void Awake()
{
_originalTmp = GetComponent<TextMeshProUGUI>();
_originalText = _originalTmp.text;
_originalTmp.enabled = false;
}
private void OnEnable()
{
BuildLetterObjects();
_shiftLoopRoutineHandle = StartCoroutine(ShiftLoopRoutine());
}
private void OnDisable()
{
if (_shiftLoopRoutineHandle != null)
StopCoroutine(_shiftLoopRoutineHandle);
}
private void OnDestroy()
{
DestroyLetterObjects();
}
#endregion
#region Public Methods
public void SetText(string newText)
{
_originalText = newText;
BuildLetterObjects();
}
#endregion
#region Private Methods
private void BuildLetterObjects()
{
DestroyLetterObjects();
foreach (char character in _originalText)
{
GameObject letterGo = new GameObject($"Letter_{character}");
letterGo.transform.SetParent(transform, false);
TextMeshProUGUI letterTmp = letterGo.AddComponent<TextMeshProUGUI>();
letterTmp.text = character.ToString();
letterTmp.fontSize = _fontSize;
letterTmp.color = _textColor;
letterTmp.alignment = TextAlignmentOptions.Center;
_letterObjects.Add(letterTmp);
}
ArrangeLetters();
ShuffleFonts();
}
private void DestroyLetterObjects()
{
foreach (TextMeshProUGUI letter in _letterObjects)
{
if (letter != null)
Destroy(letter.gameObject);
}
_letterObjects.Clear();
}
private void ArrangeLetters()
{
float totalWidth = 0f;
List<float> letterWidths = new List<float>();
foreach (TextMeshProUGUI letter in _letterObjects)
{
letter.ForceMeshUpdate();
float width = letter.preferredWidth;
letterWidths.Add(width);
totalWidth += width;
}
float currentX = -totalWidth / 2f;
for (int i = 0; i < _letterObjects.Count; i++)
{
RectTransform rt = _letterObjects[i].GetComponent<RectTransform>();
rt.anchoredPosition = new Vector2(currentX + letterWidths[i] / 2f, 0f);
rt.sizeDelta = new Vector2(letterWidths[i] + 2f, _fontSize * 1.5f);
currentX += letterWidths[i];
}
}
private void ShuffleFonts()
{
if (_fonts == null || _fonts.Length == 0)
{
Debug.LogWarning($"[{nameof(PerLetterFontShifter)}] No fonts assigned.", this);
return;
}
StartCoroutine(ShuffleStaggeredRoutine());
}
private List<int> GetShuffledIndices()
{
List<int> indices = new List<int>();
for (int i = 0; i < _letterObjects.Count; i++)
indices.Add(i);
for (int i = indices.Count - 1; i > 0; i--)
{
int j = Random.Range(0, i + 1);
(indices[i], indices[j]) = (indices[j], indices[i]);
}
return indices;
}
#endregion
#region Coroutines
private IEnumerator ShiftLoopRoutine()
{
while (true)
{
yield return new WaitForSeconds(_shiftInterval);
ShuffleFonts();
}
}
private IEnumerator ShuffleStaggeredRoutine()
{
List<int> shuffledIndices = GetShuffledIndices();
foreach (int index in shuffledIndices)
{
TextMeshProUGUI letter = _letterObjects[index];
if (letter.text == " " || letter.text == "\n")
continue;
letter.font = _fonts[Random.Range(0, _fonts.Length)];
yield return new WaitForSeconds(Random.Range(_minLetterDelay, _maxLetterDelay));
}
}
#endregion
#if UNITY_EDITOR
[ContextMenu("Test Shuffle Now")]
private void TestShuffle() => ShuffleFonts();
#endif
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2480089bca340ef4994895faaa7b6740