using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; [System.Serializable] public class CharacterExpression { public string characterName; public string expression; // default, happy, confused, sad public Sprite sprite; } public class CharacterManager : MonoBehaviour { [Header("Character Slot")] public Image leftSlot; public Image rightSlot; [Header("Expression List")] public List expressions; [Header("Animation Settings")] public float fadeSpeed = 5f; public float moveSpeed = 5f; public float offsetX = 200f; private Dictionary expressionDict; private Coroutine highlightRoutine; private Coroutine currentRoutine; private string leftCharacter = ""; private string rightCharacter = ""; private string leftExpression = ""; private string rightExpression = ""; void Start() { expressionDict = new Dictionary(); foreach (var exp in expressions) { string key = exp.characterName.Trim().ToLower() + ":" + exp.expression.Trim().ToLower(); expressionDict[key] = exp.sprite; } ResetCharacters(); } // ================= SHOW CHARACTER ================= public void ShowCharacter(string name, string exp = "default") { string key = name.Trim().ToLower() + ":" + exp.Trim().ToLower(); if (!expressionDict.ContainsKey(key)) { Debug.LogWarning("Expression not found: " + key); return; } // 🔥 STOP semua animasi sebelumnya if (currentRoutine != null) StopCoroutine(currentRoutine); currentRoutine = StartCoroutine(HandleCharacter(name, exp, key)); } // ================= SPAWN ================= IEnumerator SpawnLeft(string name, string exp, string key) { leftCharacter = name; leftExpression = exp; leftSlot.sprite = expressionDict[key]; // ✅ FIX leftSlot.gameObject.SetActive(true); yield return AnimateIn(leftSlot, -offsetX); } IEnumerator SpawnRight(string name, string exp, string key) { rightCharacter = name; rightExpression = exp; rightSlot.sprite = expressionDict[key]; rightSlot.gameObject.SetActive(true); yield return AnimateIn(rightSlot, offsetX); } // ================= REPLACE ================= IEnumerator ReplaceRight(string name, string exp, string key) { yield return AnimateOut(rightSlot, offsetX); rightCharacter = name; rightExpression = exp; rightSlot.sprite = expressionDict[key]; rightSlot.gameObject.SetActive(true); yield return AnimateIn(rightSlot, offsetX); } // ================= CHANGE EXPRESSION ================= IEnumerator ChangeExpression(Image img, string key) { yield return Fade(img, 1f, 0.5f); img.sprite = expressionDict[key]; yield return Fade(img, 0.5f, 1f); } IEnumerator HandleCharacter(string name, string exp, string key) { // ================= UPDATE EXPRESSION ================= if (leftCharacter == name) { if (leftExpression != exp) yield return ChangeExpression(leftSlot, key); leftExpression = exp; yield break; } if (rightCharacter == name) { if (rightExpression != exp) yield return ChangeExpression(rightSlot, key); rightExpression = exp; yield break; } // ================= SPAWN ================= if (leftCharacter == "") { yield return SpawnLeft(name, exp, key); } else if (rightCharacter == "") { yield return SpawnRight(name, exp, key); } else { yield return ReplaceRight(name, exp, key); } } // ================= ANIMATION ================= IEnumerator AnimateIn(Image img, float direction) { RectTransform rt = img.GetComponent(); Vector2 endPos = rt.anchoredPosition; Vector2 startPos = endPos + new Vector2(direction, 0); rt.anchoredPosition = startPos; Color c = img.color; c.a = 0f; img.color = c; float t = 0; while (t < 1f) { t += Time.deltaTime * moveSpeed; rt.anchoredPosition = Vector2.Lerp(startPos, endPos, t); c.a = Mathf.Lerp(0, 1, t); img.color = c; yield return null; } rt.anchoredPosition = endPos; c.a = 1f; img.color = c; } IEnumerator AnimateOut(Image img, float direction) { RectTransform rt = img.GetComponent(); Vector2 startPos = rt.anchoredPosition; Vector2 endPos = startPos + new Vector2(direction, 0); Color c = img.color; float t = 0; while (t < 1f) { t += Time.deltaTime * moveSpeed; rt.anchoredPosition = Vector2.Lerp(startPos, endPos, t); c.a = Mathf.Lerp(1, 0, t); img.color = c; yield return null; } img.gameObject.SetActive(false); } IEnumerator Fade(Image img, float from, float to) { Color c = img.color; float t = 0; while (t < 1f) { t += Time.deltaTime * fadeSpeed; c.a = Mathf.Lerp(from, to, t); img.color = c; yield return null; } } // ================= HIGHLIGHT ================= public void Highlight(string fullName) { string name = fullName.Split(':')[0]; if (highlightRoutine != null) StopCoroutine(highlightRoutine); highlightRoutine = StartCoroutine(DoHighlight(name)); } IEnumerator DoHighlight(string activeName) { if (leftCharacter != "") yield return SetHighlight(leftSlot, leftCharacter == activeName); if (rightCharacter != "") yield return SetHighlight(rightSlot, rightCharacter == activeName); } IEnumerator SetHighlight(Image img, bool active) { float target = active ? 1f : 0.4f; Color c = img.color; float t = 0; float start = c.a; while (t < 1f) { t += Time.deltaTime * fadeSpeed; c.a = Mathf.Lerp(start, target, t); img.color = c; yield return null; } c.a = target; img.color = c; } // ================= RESET ================= public void ResetCharacters() { StopAllCoroutines(); leftCharacter = ""; rightCharacter = ""; leftSlot.gameObject.SetActive(false); rightSlot.gameObject.SetActive(false); } }