245 lines
7.4 KiB
C#
245 lines
7.4 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
/// <summary>
|
|
/// Auto-spawns in Level01 and displays an intro subtitle sequence.
|
|
/// </summary>
|
|
public class Level01IntroSubtitles : MonoBehaviour
|
|
{
|
|
[System.Serializable]
|
|
private struct SubtitleLine
|
|
{
|
|
public string speaker;
|
|
public string text;
|
|
public float duration;
|
|
}
|
|
|
|
[Header("Trigger")]
|
|
[SerializeField] private string targetSceneName = "Level01";
|
|
[SerializeField] private float initialDelay = 2.5f;
|
|
|
|
[Header("Subtitle Sequence")]
|
|
[SerializeField] private SubtitleLine[] lines =
|
|
{
|
|
new SubtitleLine { speaker = "SYSTEME", text = "...Ici, quelque chose cloche.", duration = 2.5f },
|
|
new SubtitleLine { speaker = "SYSTEME", text = "Reste calme. Observe la piece.", duration = 2.5f },
|
|
new SubtitleLine { speaker = "SYSTEME", text = "Trouve une sortie.", duration = 2.2f },
|
|
};
|
|
|
|
[SerializeField] private float typewriterCharsPerSecond = 40f;
|
|
[SerializeField] private float fadeDuration = 0.2f;
|
|
[SerializeField] private float gapBetweenLines = 0.15f;
|
|
|
|
[Header("Visual")]
|
|
[SerializeField] private int fontSize = 28;
|
|
[SerializeField] private int speakerFontSize = 18;
|
|
[SerializeField] private float horizontalPadding = 28f;
|
|
[SerializeField] private float bottomOffset = 56f;
|
|
[SerializeField] private Color textColor = new Color(1f, 1f, 1f, 1f);
|
|
[SerializeField] private Color speakerColor = new Color(1f, 0.85f, 0.35f, 1f);
|
|
[SerializeField] private Color backgroundColor = new Color(0f, 0f, 0f, 0.62f);
|
|
|
|
private static bool s_bootstrapped;
|
|
|
|
private string m_currentSpeaker;
|
|
private string m_currentText;
|
|
private GUIStyle m_textStyle;
|
|
private GUIStyle m_speakerStyle;
|
|
private Texture2D m_background;
|
|
private bool m_isShowing;
|
|
private float m_alpha;
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
|
private static void ResetBootstrapFlag()
|
|
{
|
|
s_bootstrapped = false;
|
|
}
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|
private static void Bootstrap()
|
|
{
|
|
if (s_bootstrapped)
|
|
return;
|
|
|
|
s_bootstrapped = true;
|
|
|
|
GameObject go = new GameObject(nameof(Level01IntroSubtitles));
|
|
go.hideFlags = HideFlags.DontSave;
|
|
go.AddComponent<Level01IntroSubtitles>();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
Scene activeScene = SceneManager.GetActiveScene();
|
|
if (activeScene.name != targetSceneName)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
StartCoroutine(PlaySequence());
|
|
}
|
|
|
|
private IEnumerator PlaySequence()
|
|
{
|
|
if (initialDelay > 0f)
|
|
yield return new WaitForSeconds(initialDelay);
|
|
|
|
for (int i = 0; i < lines.Length; i++)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(lines[i].text) || lines[i].duration <= 0f)
|
|
continue;
|
|
|
|
yield return StartCoroutine(ShowLine(lines[i]));
|
|
|
|
if (gapBetweenLines > 0f)
|
|
yield return new WaitForSeconds(gapBetweenLines);
|
|
}
|
|
|
|
m_currentSpeaker = string.Empty;
|
|
m_currentText = string.Empty;
|
|
Destroy(gameObject);
|
|
}
|
|
|
|
private IEnumerator ShowLine(SubtitleLine line)
|
|
{
|
|
m_currentSpeaker = line.speaker;
|
|
m_currentText = string.Empty;
|
|
m_isShowing = true;
|
|
|
|
if (fadeDuration > 0f)
|
|
{
|
|
float fadeIn = 0f;
|
|
while (fadeIn < fadeDuration)
|
|
{
|
|
fadeIn += Time.deltaTime;
|
|
m_alpha = Mathf.Clamp01(fadeIn / fadeDuration);
|
|
yield return null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_alpha = 1f;
|
|
}
|
|
|
|
float typeTime = 0f;
|
|
int totalChars = line.text.Length;
|
|
if (typewriterCharsPerSecond > 0f)
|
|
{
|
|
while (m_currentText.Length < totalChars)
|
|
{
|
|
typeTime += Time.deltaTime;
|
|
int visibleChars = Mathf.Clamp(Mathf.FloorToInt(typeTime * typewriterCharsPerSecond), 0, totalChars);
|
|
m_currentText = line.text.Substring(0, visibleChars);
|
|
yield return null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_currentText = line.text;
|
|
}
|
|
|
|
float holdDuration = Mathf.Max(0f, line.duration - (typewriterCharsPerSecond > 0f ? typeTime : 0f));
|
|
if (holdDuration > 0f)
|
|
yield return new WaitForSeconds(holdDuration);
|
|
|
|
if (fadeDuration > 0f)
|
|
{
|
|
float fadeOut = fadeDuration;
|
|
while (fadeOut > 0f)
|
|
{
|
|
fadeOut -= Time.deltaTime;
|
|
m_alpha = Mathf.Clamp01(fadeOut / fadeDuration);
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
m_alpha = 0f;
|
|
m_isShowing = false;
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
if (!m_isShowing || string.IsNullOrEmpty(m_currentText))
|
|
return;
|
|
|
|
EnsureStyles();
|
|
|
|
float maxWidth = Mathf.Min(Screen.width - 24f, 940f);
|
|
float textWidth = maxWidth - horizontalPadding * 2f;
|
|
float speakerHeight = string.IsNullOrEmpty(m_currentSpeaker)
|
|
? 0f
|
|
: m_speakerStyle.CalcHeight(new GUIContent(m_currentSpeaker), textWidth);
|
|
float textHeight = m_textStyle.CalcHeight(new GUIContent(string.IsNullOrEmpty(m_currentText) ? " " : m_currentText), textWidth);
|
|
|
|
float boxWidth = maxWidth;
|
|
float boxHeight = speakerHeight + textHeight + 28f;
|
|
float boxX = (Screen.width - boxWidth) * 0.5f;
|
|
float boxY = Screen.height - bottomOffset - boxHeight;
|
|
|
|
Rect boxRect = new Rect(boxX, boxY, boxWidth, boxHeight);
|
|
Color previousColor = GUI.color;
|
|
GUI.color = new Color(1f, 1f, 1f, m_alpha);
|
|
GUI.DrawTexture(boxRect, m_background);
|
|
|
|
float yOffset = boxRect.y + 10f;
|
|
if (!string.IsNullOrEmpty(m_currentSpeaker))
|
|
{
|
|
Rect speakerRect = new Rect(
|
|
boxRect.x + horizontalPadding,
|
|
yOffset,
|
|
textWidth,
|
|
speakerHeight);
|
|
GUI.Label(speakerRect, m_currentSpeaker, m_speakerStyle);
|
|
yOffset += speakerHeight + 2f;
|
|
}
|
|
|
|
Rect textRect = new Rect(
|
|
boxRect.x + horizontalPadding,
|
|
yOffset,
|
|
textWidth,
|
|
textHeight);
|
|
|
|
GUI.Label(textRect, m_currentText, m_textStyle);
|
|
GUI.color = previousColor;
|
|
}
|
|
|
|
private void EnsureStyles()
|
|
{
|
|
if (m_textStyle != null)
|
|
return;
|
|
|
|
m_background = new Texture2D(1, 1);
|
|
m_background.SetPixel(0, 0, backgroundColor);
|
|
m_background.Apply();
|
|
|
|
m_textStyle = new GUIStyle(GUI.skin.label)
|
|
{
|
|
alignment = TextAnchor.MiddleCenter,
|
|
fontSize = fontSize,
|
|
wordWrap = true,
|
|
richText = false,
|
|
clipping = TextClipping.Clip,
|
|
};
|
|
m_textStyle.normal.textColor = textColor;
|
|
|
|
m_speakerStyle = new GUIStyle(GUI.skin.label)
|
|
{
|
|
alignment = TextAnchor.MiddleCenter,
|
|
fontSize = speakerFontSize,
|
|
fontStyle = FontStyle.Bold,
|
|
wordWrap = false,
|
|
clipping = TextClipping.Clip,
|
|
};
|
|
m_speakerStyle.normal.textColor = speakerColor;
|
|
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (m_background != null)
|
|
Destroy(m_background);
|
|
}
|
|
}
|