/* * FancyScrollView (https://github.com/setchi/FancyScrollView) * Copyright (c) 2020 setchi * Licensed under MIT (https://github.com/setchi/FancyScrollView/blob/master/LICENSE) */ using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using DG.Tweening; using JetBrains.Annotations; using UnityEngine; using UnityEngine.UI; using Bansonic; class UI_Panel_Character : MonoBehaviour { [SerializeField] float anim_Time = 0.5f; float Anim_Speed => 1f / anim_Time; [SerializeField] List ui_Anim; [SerializeField] Transform content_Character_Slot; [SerializeField] Button button_Character_Slot_Prefab; [SerializeField] Text text_Character_Name; [SerializeField] Image Image_Character_Illustration; [SerializeField] Image Image_Character_Illustration_BG; [Header("buttons")] public Button change_thisHero_skin; public Button thisHero_detail; public Button confirm_thisHero; [Header("Data Paths")] [Tooltip("Path relative to Resources folder for Editor mode")] public string editorResourcePath = "so/ally"; [Tooltip("Path relative to Resources folder for Runtime mode")] public string runtimeResourcePath = "so/ally"; private List allyHeroList = new List(); private void Update() { if (Input.GetKeyDown(KeyCode.Escape)) { gameObject.SetActive(false); } } private Vector2 originalIllustrationPos; private Vector2 originalIllustrationBGPos; private bool hasCachedPositions = false; private const string SAVED_HERO_ID_KEY = "SelectedMainHeroID"; void Start() { UnityEngine.Debug.Log($"[UI_Panel_Character] Start called. Illustration: {Image_Character_Illustration}"); // 初始化按钮监听 if (change_thisHero_skin != null) change_thisHero_skin.onClick.AddListener(() => gNotice.warning.display("此版本未开放皮肤切换功能")); if (thisHero_detail != null) thisHero_detail.onClick.AddListener(() => gNotice.warning.display("此版本未开放详情查看功能")); if (confirm_thisHero != null) confirm_thisHero.onClick.AddListener(OnConfirmHeroClicked); if (Image_Character_Illustration != null) { // 设置为图示的数值:Pos X: 376, Pos Y: -306 Image_Character_Illustration.rectTransform.anchoredPosition = new Vector2(376, -306); originalIllustrationPos = Image_Character_Illustration.rectTransform.anchoredPosition; if (Image_Character_Illustration.transform.parent.TryGetComponent(out CanvasGroup canvasGroup)) { canvasGroup.alpha = 0; } } if (Image_Character_Illustration_BG != null) { // 设置运行时 X 值为 376 Vector2 pos = Image_Character_Illustration_BG.rectTransform.anchoredPosition; pos.x = 376; Image_Character_Illustration_BG.rectTransform.anchoredPosition = pos; originalIllustrationBGPos = Image_Character_Illustration_BG.rectTransform.anchoredPosition; } hasCachedPositions = true; foreach (var item in ui_Anim) { if (item != null) item.speed = Anim_Speed; } if (content_Character_Slot != null) content_Character_Slot.Get_Childrens_Component(true, true); // Load AllyHero_SO data string path = Application.isEditor ? editorResourcePath : runtimeResourcePath; var loadedData = Resources.LoadAll(path); allyHeroList = new List(loadedData); UnityEngine.Debug.Log($"[UI_Panel_Character] Loaded {allyHeroList.Count} heroes from {path}"); // Ensure consistent order with UI_Panel_Main allyHeroList.Sort((a, b) => a.ally_heroID.CompareTo(b.ally_heroID)); // 读取保存的角色 ID int savedHeroID = PlayerPrefs.GetInt(SAVED_HERO_ID_KEY, -1); int initialIndex = 0; for (int i = 0; i < allyHeroList.Count; i++) { var obj = Instantiate(button_Character_Slot_Prefab, content_Character_Slot); // Register UI sounds for the newly instantiated button UISystemBootstrap.RegisterHierarchy(obj.gameObject); var data = allyHeroList[i]; // 如果 ID 匹配,设置初始索引 if (savedHeroID != -1 && data.ally_heroID == savedHeroID) { initialIndex = i; } if (obj.image != null) { obj.image.sprite = data.ally_heroSelectIcon; obj.image.preserveAspect = true; // 保持比例,防止拉伸变形 obj.image.type = Image.Type.Simple; // 确保是普通显示模式 // 确保 RectTransform 撑满父物体并居中 obj.image.rectTransform.anchorMin = Vector2.zero; obj.image.rectTransform.anchorMax = Vector2.one; obj.image.rectTransform.sizeDelta = Vector2.zero; obj.image.rectTransform.anchoredPosition = Vector2.zero; } if (obj.TryGetComponent(out UI_Button_Character_Head_Slot head_Slot)) { head_Slot.index = i; int capturedIndex = i; obj.onClick.AddListener(() => Set_Character_Index(capturedIndex)); } } // 应用初始索引(来自保存的 ID 或默认 0) UI_Panel_Main.Singleton.Character_Index = initialIndex; // Initial character display Set_Character(); } public void Set_Character_Index(int index) { if (UI_Panel_Main.Singleton.Character_Index == index) return; UI_Panel_Main.Singleton.Character_Index = index; Set_Character(); // 人性化逻辑:点击头像即自动设为看板并保存,并显示提示内容 SaveCurrentCharacter(true); } private void OnConfirmHeroClicked() { if (SaveCurrentCharacter(true)) { // 确认按钮逻辑:保存后禁用自身物体(隐藏面板) gameObject.SetActive(false); } } private bool SaveCurrentCharacter(bool showNotice) { int currentIndex = UI_Panel_Main.Singleton.Character_Index; if (allyHeroList != null && currentIndex >= 0 && currentIndex < allyHeroList.Count) { int heroID = allyHeroList[currentIndex].ally_heroID; PlayerPrefs.SetInt(SAVED_HERO_ID_KEY, heroID); PlayerPrefs.Save(); if (showNotice) { gNotice.alarm.display($"已将 {allyHeroList[currentIndex].ally_heroName} 设置为记录对象。"); } // 同步更新主面板的看板图 UI_Panel_Main.Singleton.Character_Index = currentIndex; return true; } return false; } private void OnEnable() { Set_Character(); } Coroutine c_Character_Illustration_Anim; public void Set_Character() { if (c_Character_Illustration_Anim != null) { StopCoroutine(c_Character_Illustration_Anim); } if (Image_Character_Illustration.transform.parent.TryGetComponent(out CanvasGroup canvasGroup)) { c_Character_Illustration_Anim = StartCoroutine(C_Character_Illustration_Anim(canvasGroup, Set_Character_Show)); } } public void Set_Character_Show() { int index = UI_Panel_Main.Singleton.Character_Index; if (allyHeroList == null || index < 0 || index >= allyHeroList.Count) return; // 停止之前的 Tween 以防冲突 Image_Character_Illustration.rectTransform.DOKill(); Image_Character_Illustration_BG.rectTransform.DOKill(); text_Character_Name.DOKill(); var data = allyHeroList[index]; // 使用初始缓存的坐标,防止频繁点击导致的偏移累积 Vector2 targetPos1 = hasCachedPositions ? originalIllustrationPos : Image_Character_Illustration.rectTransform.anchoredPosition; Image_Character_Illustration.sprite = data.ally_hero_HD_image; // 动画:从左侧 200 像素滑入到目标位置 float startX1 = targetPos1.x - 200; Image_Character_Illustration.rectTransform.anchoredPosition = new Vector2(startX1, targetPos1.y); Image_Character_Illustration.rectTransform.DOAnchorPos(targetPos1, anim_Time) .SetEase(Ease.OutCubic) .SetLink(Image_Character_Illustration.gameObject); Vector2 targetPosBG = hasCachedPositions ? originalIllustrationBGPos : Image_Character_Illustration_BG.rectTransform.anchoredPosition; Image_Character_Illustration_BG.sprite = data.ally_hero_HD_image; float startXBG = targetPosBG.x - 200; Image_Character_Illustration_BG.rectTransform.anchoredPosition = new Vector2(startXBG, targetPosBG.y); Image_Character_Illustration_BG.rectTransform.DOAnchorPos(targetPosBG, anim_Time) .SetEase(Ease.OutCubic) .SetLink(Image_Character_Illustration_BG.gameObject); Image_Character_Illustration_BG.transform.localScale = Vector3.one; string text = data.ally_heroName; text_Character_Name.text = string.Empty; text_Character_Name.DOText(text, anim_Time) .SetEase(Ease.Linear) .SetLink(text_Character_Name.gameObject); } IEnumerator C_Character_Illustration_Anim(CanvasGroup canvasGroup, Action onHide) { while (canvasGroup.alpha > 0) { canvasGroup.alpha -= Anim_Speed * Time.deltaTime; yield return null; } onHide?.Invoke(); while (canvasGroup.alpha < 1) { canvasGroup.alpha += Anim_Speed * Time.deltaTime; yield return null; } } }