using UnityEngine; using System.Collections; public class Animation_GenerateJudgementSituationPrefab : MonoBehaviour { public static Animation_GenerateJudgementSituationPrefab Instance; [Header("����λ�� (������)")] public GameObject redEffect; public GameObject greenEffect; public GameObject yellowEffect; public GameObject purpleEffect; public GameObject blueEffect; [Header("�ж�Ʈ�� Prefabs")] public GameObject perfect_judge_prefab; public GameObject great_judge_prefab; public GameObject good_judge_prefab; public GameObject miss_judge_prefab; [Header("���������")] public float baseScale = 1.0f; public bool useRandomScale = true; public float minScaleMultiplier = 0.8f; public float maxScaleMultiplier = 1.2f; [Header("������Ծ����")] public float jumpForce = 5.0f; // ���ϵ���ij�ʼ�ٶ� public float gravity = -12.0f; // ���� [Header("ʱ����͸���ȿ��� (��)")] public float fadeInTime = 0.1f; // ���ɺ��������ɽ��� (0->1) public float fadeOutStartTime = 0.6f; // ���ɺ�ڼ��뿪ʼ���� public float fadeOutDuration = 0.3f; // ������������ʱ�� // Cache spawn transforms to avoid accessing destroyed GameObject references. private Transform redSpawn; private Transform greenSpawn; private Transform yellowSpawn; private Transform purpleSpawn; private Transform blueSpawn; // Track last scene to detect scene changes private int lastSceneIndex = -1; private void Awake() { if (Instance == null) { Instance = this; // ע�⣺������һ�δ���ʱ�������������¼��� // DontDestroyOnLoad(gameObject); // �� �Ƴ������������������¼���ʱ������ } else if (Instance != this) { Destroy(gameObject); return; } CacheSpawnPoints(); lastSceneIndex = UnityEngine.SceneManagement.SceneManager.GetActiveScene().buildIndex; } private void Start() { // Ensure spawn points are cached after all scene objects are initialized CacheSpawnPointsIfNeeded(); } private void OnEnable() { // Detect scene reload and refresh cache int currentSceneIndex = UnityEngine.SceneManagement.SceneManager.GetActiveScene().buildIndex; if (currentSceneIndex != lastSceneIndex) { if (JudgeManager.IsDebugEnabled) Debug.Log($"[Animation_Generate] Scene changed detected (from {lastSceneIndex} to {currentSceneIndex}), refreshing spawn point cache"); lastSceneIndex = currentSceneIndex; CacheSpawnPoints(); } else { CacheSpawnPointsIfNeeded(); } } private void CacheSpawnPointsIfNeeded() { // Only recache if any of the references appear to be invalid (destroyed) if (redSpawn == null || greenSpawn == null || yellowSpawn == null || purpleSpawn == null || blueSpawn == null) { // Check if the effect GameObjects are still valid bool anyInvalid = (redEffect == null || redEffect.transform == null) || (greenEffect == null || greenEffect.transform == null) || (yellowEffect == null || yellowEffect.transform == null) || (purpleEffect == null || purpleEffect.transform == null) || (blueEffect == null || blueEffect.transform == null); if (anyInvalid || redSpawn == null) { CacheSpawnPoints(); } } } private void CacheSpawnPoints() { // Important: check Unity "fake null" before accessing .transform redSpawn = redEffect != null ? redEffect.transform : null; greenSpawn = greenEffect != null ? greenEffect.transform : null; yellowSpawn = yellowEffect != null ? yellowEffect.transform : null; purpleSpawn = purpleEffect != null ? purpleEffect.transform : null; blueSpawn = blueEffect != null ? blueEffect.transform : null; if (JudgeManager.IsDebugEnabled) { Debug.Log($"[Animation_Generate] Cached spawn points: red={redSpawn!=null}, green={greenSpawn!=null}, yellow={yellowSpawn!=null}, purple={purpleSpawn!=null}, blue={blueSpawn!=null}"); } } public void SpawnJudgePrefab(string color, string judgeResult) { if (string.IsNullOrEmpty(color)) { Debug.LogError("[Animation_Generate] SpawnJudgePrefab called with empty color!"); return; } if (string.IsNullOrEmpty(judgeResult)) { Debug.LogError("[Animation_Generate] SpawnJudgePrefab called with empty judgeResult!"); return; } Transform spawnPoint = GetSpawnPoint(color); if (spawnPoint == null) { Debug.LogError($"[Animation_Generate] Could not find spawn point for color: {color}"); return; } GameObject prefabToUse = GetJudgePrefab(judgeResult); if (prefabToUse == null) { Debug.LogError($"[Animation_Generate] Could not find judge prefab for result: {judgeResult}. Available: perfect={perfect_judge_prefab != null}, great={great_judge_prefab != null}, good={good_judge_prefab != null}, miss={miss_judge_prefab != null}"); return; } if (JudgeManager.IsDebugEnabled) Debug.Log($"[Animation_Generate] Spawning judge prefab: color={color}, result={judgeResult}, prefab={prefabToUse.name}"); GameObject instance = Instantiate(prefabToUse, spawnPoint); instance.transform.localPosition = Vector3.zero; // �������� float finalScale = baseScale; if (useRandomScale) finalScale *= Random.Range(minScaleMultiplier, maxScaleMultiplier); instance.transform.localScale = new Vector3(finalScale, finalScale, 1f); // �����˶��߼� StartCoroutine(AnimateSprite(instance)); } private IEnumerator AnimateSprite(GameObject obj) { if (obj == null) yield break; SpriteRenderer sr = obj.GetComponent(); float elapsed = 0f; float vVelocity = jumpForce; Vector3 currentLocalPos = Vector3.zero; // �������������ڣ���ʼ������ʱ�� + ����������ʱ�� float totalLifeTime = fadeOutStartTime + fadeOutDuration; // ��ʼ͸���� if (sr != null) { Color c = sr.color; c.a = 0f; sr.color = c; } // ֻҪû�����������ͳ���ִ�� while (elapsed < totalLifeTime) { if (obj == null) yield break; float dt = Time.deltaTime; elapsed += dt; // --- 1. ����λ�� --- vVelocity += gravity * dt; currentLocalPos.y += vVelocity * dt; obj.transform.localPosition = currentLocalPos; // --- 2. ͸�����߼� (��������) --- if (sr != null) { float alpha; // ���Խ׶Σ���ǰʱ�� < fadeInTime if (elapsed < fadeInTime) { alpha = Mathf.InverseLerp(0f, fadeInTime, elapsed); } // �����׶Σ���ǰʱ�� > fadeOutStartTime else if (elapsed > fadeOutStartTime) { // �� fadeOutStartTime �� totalLifeTime ֮��� 1 �䵽 0 alpha = Mathf.InverseLerp(totalLifeTime, fadeOutStartTime, elapsed); } // �м���ȫ��ʾ�׶� else { alpha = 1f; } Color c = sr.color; c.a = Mathf.Clamp01(alpha); sr.color = c; } yield return null; } // --- ȷ�����һ֡����ȫ͸���� --- if (obj != null && sr != null) { Color c = sr.color; c.a = 0f; sr.color = c; } // �ȴ���Ⱦ��ɣ���ֹ��ɾ yield return new WaitForEndOfFrame(); if (obj != null) Destroy(obj); } private Transform GetSpawnPoint(string color) { if (string.IsNullOrEmpty(color)) return null; // ��ÿ�ε���ʱ����Ƿ���Ҫ���»��� CacheSpawnPointsIfNeeded(); Transform point = null; switch (color.ToLower()) { case "red": point = redSpawn; break; case "green": point = greenSpawn; break; case "yellow": point = yellowSpawn; break; case "purple": point = purpleSpawn; break; case "blue": point = blueSpawn; break; default: Debug.LogWarning($"[Animation_Generate] Unknown color: {color}"); return null; } if (point == null) { Debug.LogError($"[Animation_Generate] Spawn point for color {color} is null. Check if effects are assigned in inspector. Make sure the effect object is active in the scene."); } return point; } private GameObject GetJudgePrefab(string result) { if (string.IsNullOrEmpty(result)) return null; GameObject prefab = null; switch (result.ToLower()) { case "perfect": prefab = perfect_judge_prefab; break; case "great": prefab = great_judge_prefab; break; case "good": prefab = good_judge_prefab; break; case "miss": prefab = miss_judge_prefab; break; default: Debug.LogWarning($"[Animation_Generate] Unknown judge result: {result}"); return null; } if (prefab == null) { Debug.LogError($"[Animation_Generate] Judge prefab for '{result}' is not assigned in inspector! Check Animation_GenerateJudgementSituationPrefab component."); } return prefab; } }