using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using System.Collections; public class newTeamSelector : MonoBehaviour { public static newTeamSelector Instance { get; private set; } [Header("Inspector")] public Sprite levelIcon_sprite_C; public Sprite levelIcon_sprite_B; public Sprite levelIcon_sprite_A; public Sprite levelIcon_sprite_S; [Header("Inspector")] public int selected_heroSlot01_heroID; public int selected_heroSlot02_heroID; public int selected_heroSlot03_heroID; public int selected_heroSlot04_heroID; public int selected_heroSlot05_heroID; [Tooltip("Prefab for a single hero slot. Must contain slots_heroSlots component.")] public GameObject slotPrefab; [Tooltip("Container (GameObject with HorizontalLayoutGroup) where slots will be instantiated")] public RectTransform container; [Tooltip("Number of slots to create (default 5)")] public int slotCount = 5; [Tooltip("Optional override colors used for header images per slot. If not set, prefab's headerImage_colors will be used.")] public Color[] overrideHeaderColors; [Tooltip("If true, create slots automatically on Start")] public bool instantiateOnStart = true; [Tooltip("Delay skill list rebuild until after slot enter animation to reduce hitching.")] public float delayedSkillRefreshSeconds = 0.75f; private readonly List createdSlots = new List(); private static AllyHero_SO[] cachedHeroes; private static Dictionary cachedHeroesById; private Coroutine refreshSkillsRoutine; void Awake() { if (Instance == null) { Instance = this; EnsureHeroCache(); } else { Destroy(gameObject); } } void Start() { if (instantiateOnStart) CreateSlots(); StartCoroutine(LoadSelectedHeroesNextFrame()); } void Update() { } private IEnumerator LoadSelectedHeroesNextFrame() { yield return null; LoadSelectedHeroes(); } public void CreateSlots() { if (slotPrefab == null || container == null) { Debug.LogError("newTeamSelector: slotPrefab or container is not assigned."); return; } // Clear existing for (int i = container.childCount - 1; i >= 0; i--) { var c = container.GetChild(i); #if UNITY_EDITOR if (!Application.isPlaying) DestroyImmediate(c.gameObject); else Destroy(c.gameObject); #else Destroy(c.gameObject); #endif } createdSlots.Clear(); for (int i = 0; i < slotCount; i++) { var go = Instantiate(slotPrefab, container); go.transform.SetParent(container, false); go.name = $"heroSlot_{i}"; var slotComp = go.GetComponent(); if (slotComp == null) { Debug.LogWarning("newTeamSelector: instantiated prefab does not contain slots_heroSlots component."); continue; } slotComp.heroSlot_slotID = i; // choose color: overrideHeaderColors takes priority, then prefab's headerImage_colors if available Color chosen = Color.white; if (overrideHeaderColors != null && i < overrideHeaderColors.Length) { chosen = overrideHeaderColors[i]; } else if (slotComp.headerImage_colors != null && i < slotComp.headerImage_colors.Length) { chosen = slotComp.headerImage_colors[i]; } // Ensure visible alpha chosen.a = Mathf.Clamp01(chosen.a); if (chosen.a <= 0f) chosen.a = 1f; // Apply immediately if possible if (slotComp.heroSlot_colorImage != null) { slotComp.heroSlot_colorImage.color = chosen; } createdSlots.Add(slotComp); } // Force immediate layout rebuild so HorizontalLayoutGroup arranges children right away LayoutRebuilder.ForceRebuildLayoutImmediate(container); // Re-apply colors next frame to override any Start() logic on instantiated prefabs StartCoroutine(ApplyHeaderColorsNextFrame()); } private IEnumerator ApplyHeaderColorsNextFrame() { yield return null; // wait one frame for (int i = 0; i < createdSlots.Count; i++) { var slot = createdSlots[i]; if (slot == null) continue; Color chosen = Color.white; if (overrideHeaderColors != null && i < overrideHeaderColors.Length) { chosen = overrideHeaderColors[i]; } else if (slot.headerImage_colors != null && i < slot.headerImage_colors.Length) { chosen = slot.headerImage_colors[i]; } chosen.a = 1f; if (slot.heroSlot_colorImage == null) { var img = slot.GetComponentInChildren(true); if (img != null) slot.heroSlot_colorImage = img; } if (slot.heroSlot_colorImage != null) slot.heroSlot_colorImage.color = chosen; } // ensure layout rebuilt after modifications LayoutRebuilder.ForceRebuildLayoutImmediate(container); } public List GetCreatedSlots() => createdSlots; public void UpdateAndSaveSelectedHeroes() { if (createdSlots.Count > 0) selected_heroSlot01_heroID = createdSlots[0].heroSlot_heroID; if (createdSlots.Count > 1) selected_heroSlot02_heroID = createdSlots[1].heroSlot_heroID; if (createdSlots.Count > 2) selected_heroSlot03_heroID = createdSlots[2].heroSlot_heroID; if (createdSlots.Count > 3) selected_heroSlot04_heroID = createdSlots[3].heroSlot_heroID; if (createdSlots.Count > 4) selected_heroSlot05_heroID = createdSlots[4].heroSlot_heroID; PlayerPrefs.SetInt("selected_heroSlot01_heroID", selected_heroSlot01_heroID); PlayerPrefs.SetInt("selected_heroSlot02_heroID", selected_heroSlot02_heroID); PlayerPrefs.SetInt("selected_heroSlot03_heroID", selected_heroSlot03_heroID); PlayerPrefs.SetInt("selected_heroSlot04_heroID", selected_heroSlot04_heroID); PlayerPrefs.SetInt("selected_heroSlot05_heroID", selected_heroSlot05_heroID); PlayerPrefs.Save(); Debug.Log("已保存当前英雄到 PlayerPrefs"); } public void LoadSelectedHeroes() { if (createdSlots.Count == 0) return; selected_heroSlot01_heroID = PlayerPrefs.GetInt("selected_heroSlot01_heroID", 0); selected_heroSlot02_heroID = PlayerPrefs.GetInt("selected_heroSlot02_heroID", 0); selected_heroSlot03_heroID = PlayerPrefs.GetInt("selected_heroSlot03_heroID", 0); selected_heroSlot04_heroID = PlayerPrefs.GetInt("selected_heroSlot04_heroID", 0); selected_heroSlot05_heroID = PlayerPrefs.GetInt("selected_heroSlot05_heroID", 0); // Set the slots if (createdSlots.Count > 0) createdSlots[0].heroSlot_heroID = selected_heroSlot01_heroID; if (createdSlots.Count > 1) createdSlots[1].heroSlot_heroID = selected_heroSlot02_heroID; if (createdSlots.Count > 2) createdSlots[2].heroSlot_heroID = selected_heroSlot03_heroID; if (createdSlots.Count > 3) createdSlots[3].heroSlot_heroID = selected_heroSlot04_heroID; if (createdSlots.Count > 4) createdSlots[4].heroSlot_heroID = selected_heroSlot05_heroID; // Update each slot's UI for (int i = 0; i < createdSlots.Count; i++) { var slot = createdSlots[i]; if (slot.heroSlot_heroID != 0) { // Find the hero SO AllyHero_SO hero = FindHeroById(slot.heroSlot_heroID); if (hero != null) { // Delay expensive skill UI refresh to avoid slot-enter stutters. slot.SetSlot(slot.heroSlot_heroID, hero.ally_heroName, hero.ally_heroPoster, false); } } else { // Clear slot logic slot.heroSlot_heroID = 0; if (slot.heroSlot_heroName != null) slot.heroSlot_heroName.text = "未选择"; if (slot.heroImage != null) { // revert to default sprite if provided, otherwise keep transparent if (slot.defaultHeroSprite != null) { slot.heroImage.sprite = slot.defaultHeroSprite; slot.heroImage.color = new Color(slot.heroImage.color.r, slot.heroImage.color.g, slot.heroImage.color.b, 1f); } else { slot.heroImage.sprite = null; slot.heroImage.color = new Color(slot.heroImage.color.r, slot.heroImage.color.g, slot.heroImage.color.b, 0f); } } if (slot.heroLevelImage != null) { slot.heroLevelImage.sprite = null; slot.heroLevelImage.color = new Color(1f, 1f, 1f, 0f); } // Update skill list slot.UpdateSkillList(false); } } if (refreshSkillsRoutine != null) StopCoroutine(refreshSkillsRoutine); refreshSkillsRoutine = StartCoroutine(RefreshSkillsGradually()); } private IEnumerator RefreshSkillsGradually() { if (delayedSkillRefreshSeconds > 0f) yield return new WaitForSecondsRealtime(delayedSkillRefreshSeconds); else yield return null; for (int i = 0; i < createdSlots.Count; i++) { var slot = createdSlots[i]; if (slot == null) continue; if (slot.heroSlot_heroID != 0) { slot.UpdateSkillList(false); // Spread UI instantiation across frames to reduce hitch. yield return null; } } TeamSelectorAnimController.PlaySkillsFlash(null); refreshSkillsRoutine = null; } private AllyHero_SO FindHeroById(int id) { EnsureHeroCache(); if (cachedHeroesById != null && cachedHeroesById.TryGetValue(id, out var hero)) return hero; return null; } private static void EnsureHeroCache() { if (cachedHeroesById != null && cachedHeroesById.Count > 0) return; if (cachedHeroes == null || cachedHeroes.Length == 0) cachedHeroes = Resources.LoadAll(""); cachedHeroesById = new Dictionary(); if (cachedHeroes == null) return; for (int i = 0; i < cachedHeroes.Length; i++) { AllyHero_SO hero = cachedHeroes[i]; if (hero == null) continue; cachedHeroesById[hero.ally_heroID] = hero; } } }