Add : Shifting subtitles
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user