255 lines
8.5 KiB
C#
255 lines
8.5 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using System.Collections;
|
|
|
|
public class readyLetsGo : MonoBehaviour
|
|
{
|
|
public List<Image> _321goImages;
|
|
public GameObject _321goCanvasGO;
|
|
public CanvasGroup _321goCanvasgroup;
|
|
[Header("duration")]
|
|
[SerializeField] float fadeInDuration;
|
|
[SerializeField] float fadeOutDuration;
|
|
[SerializeField] float displayDuration;
|
|
public float oneImageDuration = 1f;
|
|
public float waitingDuration = 0.25f;
|
|
public float startScale = 1.25f;
|
|
public float endScale = 0.8f;
|
|
|
|
private Coroutine sequenceCoroutine;
|
|
|
|
// Prevent re-entry / accidental double-play
|
|
private bool isPlaying = false;
|
|
private float lastPlayedTime = -10f;
|
|
[Tooltip("Minimum seconds between automatic replays of the sequence")]
|
|
public float replayCooldown = -9999f; // set to negative to prevent replays
|
|
|
|
// Ensure the sequence only runs once per scene by default
|
|
private bool playedOnce = false;
|
|
|
|
private void Start()
|
|
{
|
|
// Ensure canvas is hidden initially
|
|
if (_321goCanvasGO != null)
|
|
{
|
|
_321goCanvasGO.SetActive(false);
|
|
}
|
|
if (_321goCanvasgroup != null)
|
|
{
|
|
_321goCanvasgroup.alpha = 0;
|
|
}
|
|
|
|
// Ensure all images are inactive at start so they don't flash on scene load.
|
|
if (_321goImages != null)
|
|
{
|
|
for (int i = 0; i < _321goImages.Count; i++)
|
|
{
|
|
var img = _321goImages[i];
|
|
if (img != null && img.gameObject.activeSelf)
|
|
{
|
|
img.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// reset play state on scene start
|
|
isPlaying = false;
|
|
lastPlayedTime = -10f;
|
|
playedOnce = false; // allow one play when player initiates
|
|
}
|
|
|
|
/// <summary>
|
|
/// Play the 3-2-1 GO sequence: fade in canvas, then cycle through images with fade in/out and scaling.
|
|
/// Duration calculation: fadeInDuration = fadeOutDuration = oneImageDuration / 5, displayDuration = oneImageDuration * 3 / 5
|
|
/// </summary>
|
|
public void PlaySequence()
|
|
{
|
|
// If already played once, do not play again
|
|
if (playedOnce) return;
|
|
|
|
// Prevent immediate replays or re-entrant calls
|
|
if (isPlaying)
|
|
{
|
|
return;
|
|
}
|
|
if (Time.unscaledTime - lastPlayedTime < replayCooldown)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Stop any existing sequence
|
|
if (sequenceCoroutine != null)
|
|
{
|
|
StopCoroutine(sequenceCoroutine);
|
|
sequenceCoroutine = null;
|
|
}
|
|
|
|
// Calculate durations based on oneImageDuration
|
|
fadeInDuration = oneImageDuration / 5f;
|
|
fadeOutDuration = oneImageDuration / 5f;
|
|
displayDuration = oneImageDuration * 3f / 5f;
|
|
|
|
isPlaying = true;
|
|
lastPlayedTime = Time.unscaledTime;
|
|
sequenceCoroutine = StartCoroutine(PlaySequenceCoroutine());
|
|
}
|
|
|
|
private IEnumerator PlaySequenceCoroutine()
|
|
{
|
|
// Activate canvas and fade in from alpha 0 to 1 over 0.25 seconds
|
|
if (_321goCanvasGO != null)
|
|
{
|
|
_321goCanvasGO.SetActive(true);
|
|
}
|
|
|
|
if (_321goCanvasgroup != null)
|
|
{
|
|
float elapsedTime = 0f;
|
|
while (elapsedTime < 0.25f)
|
|
{
|
|
elapsedTime += Time.unscaledDeltaTime;
|
|
_321goCanvasgroup.alpha = Mathf.Clamp01(elapsedTime / 0.25f);
|
|
yield return null;
|
|
}
|
|
_321goCanvasgroup.alpha = 1f;
|
|
}
|
|
|
|
// Wait for waitingDuration before starting the image sequence
|
|
float waitElapsed = 0f;
|
|
while (waitElapsed < waitingDuration)
|
|
{
|
|
waitElapsed += Time.unscaledDeltaTime;
|
|
yield return null;
|
|
}
|
|
|
|
// Cycle through images in the list
|
|
for (int i = 0; i < _321goImages.Count; i++)
|
|
{
|
|
Image currentImage = _321goImages[i];
|
|
if (currentImage == null) continue;
|
|
|
|
// Start the fade in, display, and fade out sequence for this image
|
|
yield return StartCoroutine(PlayImageSequence(currentImage));
|
|
|
|
// After the sequence finishes ensure the image is disabled (PlayImageSequence also disables,
|
|
// but keep as defensive measure)
|
|
try { if (currentImage != null) currentImage.gameObject.SetActive(false); } catch { }
|
|
|
|
// If there's a next image, the next loop iteration will activate it when needed
|
|
}
|
|
|
|
// After all images done, hide canvas again
|
|
if (_321goCanvasgroup != null)
|
|
{
|
|
// fade out canvas quickly
|
|
float elapsed = 0f;
|
|
float duration = 0.15f;
|
|
float startA = _321goCanvasgroup.alpha;
|
|
while (elapsed < duration)
|
|
{
|
|
elapsed += Time.unscaledDeltaTime;
|
|
float frac = Mathf.Clamp01(elapsed / duration);
|
|
_321goCanvasgroup.alpha = Mathf.Lerp(startA, 0f, frac);
|
|
yield return null;
|
|
}
|
|
_321goCanvasgroup.alpha = 0f;
|
|
}
|
|
if (_321goCanvasGO != null)
|
|
{
|
|
_321goCanvasGO.SetActive(false);
|
|
}
|
|
|
|
sequenceCoroutine = null;
|
|
// mark finished and record time
|
|
isPlaying = false;
|
|
lastPlayedTime = Time.unscaledTime;
|
|
playedOnce = true; // ensure it won't run again unless ResetPlayState is called
|
|
}
|
|
|
|
private IEnumerator PlayImageSequence(Image image)
|
|
{
|
|
// Ensure the image GameObject is active only for the duration of its display
|
|
try
|
|
{
|
|
if (!image.gameObject.activeSelf)
|
|
image.gameObject.SetActive(true);
|
|
}
|
|
catch { }
|
|
|
|
// Get the RectTransform for scaling
|
|
RectTransform rectTransform = image.GetComponent<RectTransform>();
|
|
if (rectTransform == null)
|
|
{
|
|
// If no rect, still wait whole duration then disable
|
|
float fallbackTotal = fadeInDuration + displayDuration + fadeOutDuration;
|
|
yield return new WaitForSecondsRealtime(fallbackTotal);
|
|
try { image.gameObject.SetActive(false); } catch { }
|
|
yield break;
|
|
}
|
|
|
|
// Initialize image alpha to 0 and scale to startScale
|
|
Color imageColor = image.color;
|
|
imageColor.a = 0f;
|
|
image.color = imageColor;
|
|
rectTransform.localScale = Vector3.one * startScale;
|
|
|
|
float totalDuration = fadeInDuration + displayDuration + fadeOutDuration;
|
|
float elapsedTime = 0f;
|
|
|
|
while (elapsedTime < totalDuration)
|
|
{
|
|
elapsedTime += Time.unscaledDeltaTime;
|
|
float normalizedTime = Mathf.Clamp01(elapsedTime / totalDuration);
|
|
|
|
// Fade in phase (0 to fadeInDuration)
|
|
if (elapsedTime < fadeInDuration)
|
|
{
|
|
float fadeInProgress = elapsedTime / Mathf.Max(0.0001f, fadeInDuration);
|
|
imageColor.a = Mathf.Lerp(0f, 1f, fadeInProgress);
|
|
}
|
|
// Display phase (fadeInDuration to fadeInDuration + displayDuration)
|
|
else if (elapsedTime < fadeInDuration + displayDuration)
|
|
{
|
|
imageColor.a = 1f;
|
|
}
|
|
// Fade out phase (fadeInDuration + displayDuration to total)
|
|
else
|
|
{
|
|
float fadeOutProgress = (elapsedTime - fadeInDuration - displayDuration) / Mathf.Max(0.0001f, fadeOutDuration);
|
|
imageColor.a = Mathf.Lerp(1f, 0f, fadeOutProgress);
|
|
}
|
|
|
|
// Apply alpha
|
|
image.color = imageColor;
|
|
|
|
// Continuous scaling from startScale to endScale throughout the entire sequence
|
|
float currentScale = Mathf.Lerp(startScale, endScale, normalizedTime);
|
|
rectTransform.localScale = Vector3.one * currentScale;
|
|
|
|
yield return null;
|
|
}
|
|
|
|
// Ensure final state
|
|
imageColor.a = 0f;
|
|
image.color = imageColor;
|
|
rectTransform.localScale = Vector3.one * endScale;
|
|
|
|
// Disable the image GameObject after finished to avoid lingering in scene
|
|
try { image.gameObject.SetActive(false); } catch { }
|
|
}
|
|
|
|
// Optional public reset if some external system wants to allow replay (e.g., scene reload)
|
|
public void ResetPlayState()
|
|
{
|
|
isPlaying = false;
|
|
lastPlayedTime = -10f;
|
|
playedOnce = false;
|
|
if (sequenceCoroutine != null)
|
|
{
|
|
try { StopCoroutine(sequenceCoroutine); } catch { }
|
|
sequenceCoroutine = null;
|
|
}
|
|
}
|
|
}
|