From d6e5a25f80afccab55ccd6e435495da921311358 Mon Sep 17 00:00:00 2001
From: hch <305670599@qq.com>
Date: 星期五, 20 三月 2026 20:23:04 +0800
Subject: [PATCH] 0312 优化所有界面用到模型的地方做延迟加载处理, 避免一次性加载过多卡顿

---
 Main/System/Hero/UIHeroController.cs |  296 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 272 insertions(+), 24 deletions(-)

diff --git a/Main/System/Hero/UIHeroController.cs b/Main/System/Hero/UIHeroController.cs
index 7ae549e..debf7a4 100644
--- a/Main/System/Hero/UIHeroController.cs
+++ b/Main/System/Hero/UIHeroController.cs
@@ -4,6 +4,7 @@
 using Spine.Unity;
 using UnityEngine;
 using UnityEngine.UI;
+using Cysharp.Threading.Tasks;
 
 public class UIHeroController : MonoBehaviour
 {
@@ -13,6 +14,10 @@
 
 	public Spine.AnimationState spineAnimationState;
 	private GameObject instanceGO;
+	private bool isInitializing = false;
+	private bool isInitialized = false;
+	private static int activeInitializationCount = 0; // 褰撳墠姝e湪鍒濆鍖栫殑鍗$墖鏁伴噺
+	private static readonly object initializationLock = new object();
 
 	public Action onComplete;
 	public void Create(int _skinID, float scale = 0.8f, Action _onComplete = null, string motionName = "idle", bool isLh = false)
@@ -127,33 +132,41 @@
 			Debug.LogError("鏈厤缃畇pine");
 			return;
 		}
-		skeletonGraphic.initialSkinName = skinConfig.InitialSkinName;
-		skeletonGraphic.Initialize(true);
-		// 鍒濆鍖栧畬鎴愬悗璁剧疆鐨偆
-		if (!string.IsNullOrEmpty(skinConfig.InitialSkinName))
+
+		// 浣跨敤 UniTask 杩涜寤惰繜鍒濆鍖栵紝閬垮厤鎵归噺鍒涘缓鏃跺崱椤�
+		if (isInitializing)
 		{
-			var skeleton = skeletonGraphic.Skeleton;
-			skeleton.SetSkin(skinConfig.InitialSkinName);
-			skeleton.SetSlotsToSetupPose();
-			skeletonGraphic.Update(0);
+			// 濡傛灉姝e湪鍒濆鍖栵紝璁剧疆鏍囧織浣嶅彇娑堜箣鍓嶇殑浠诲姟
+			isInitializing = false;
 		}
-
-		skeletonGraphic.enabled = true;
-		SetMaterialNone();
-
-		spineAnimationState = skeletonGraphic.AnimationState;
-		spineAnimationState.Data.DefaultMix = 0f;
-		if (motionName == "")
-			motionName = GetFistSpineAnim();
-
-		PlayAnimation(motionName, true);
-		spineAnimationState.Complete -= OnAnimationComplete;
-		spineAnimationState.Complete += OnAnimationComplete;
+		
+		// 绔嬬粯闇�瑕佺珛鍗虫樉绀猴紝鍏朵粬鎯呭喌寤惰繜鍒濆鍖�
+		if (isLh)
+		{
+			// 绔嬬粯绔嬪嵆鍒濆鍖�
+			ForceInitialize(motionName);
+		}
+		else
+		{
+			// 鍦ㄥ姞杞芥柊妯″瀷鍓嶅厛闅愯棌褰撳墠鏄剧ず鐨勬ā鍨嬶紙闈炵珛缁樻儏鍐碉級
+			if (skeletonGraphic != null)
+			{
+				skeletonGraphic.enabled = false;
+			}
+			
+			// 浣跨敤 UniTask 杩涜寮傛鍒濆鍖�
+			DelayedInitializeAsync(skinConfig, motionName).Forget();
+		}
 	}
 
 	public bool HasAnimation(string motionName)
 	{
-		return skeletonGraphic != null && skeletonGraphic.Skeleton != null && skeletonGraphic.Skeleton.ContainsMotion(motionName);
+		if (skeletonGraphic == null || skeletonGraphic.Skeleton == null)
+		{
+			Debug.LogWarning("skeletonGraphic or Skeleton is null, cannot check animation: " + motionName);
+			return false;
+		}
+		return skeletonGraphic.Skeleton.ContainsMotion(motionName);
 	}
 
 
@@ -169,6 +182,13 @@
 		pool = null;
 	}
 
+	private string pendingAnimationName = null;
+	private bool pendingAnimationLoop = false;
+	private bool pendingAnimationReplay = true;
+	private float? pendingSpeed = null;
+	private bool pendingEnabled = true; // 鏀逛负鏅�歜ool锛宖alse琛ㄧず鏈缃紝true琛ㄧず闇�瑕佸惎鐢�
+	private bool pendingGray = false; // 鏀逛负鏅�歜ool锛岃〃绀烘槸鍚﹂渶瑕佽缃伆搴�
+
 	/// <summary>
 	/// 鎾斁 Spine 鍔ㄧ敾
 	/// </summary>
@@ -177,18 +197,45 @@
 	/// <param name="replay">濡傛灉鐩稿悓鍔ㄤ綔鏄惁鍐嶆閲嶆挱锛屾瘮濡傝窇姝ラ噸鎾氨浼氳烦甯т笉椤烘粦</param>
 	public virtual TrackEntry PlayAnimation(string motionName, bool loop = false, bool replay = true)
 	{
-		if (spineAnimationState == null) return null;
+		// 濡傛灉姝e湪鍒濆鍖栦腑锛屼繚瀛樺姩鐢诲弬鏁帮紝绛夊緟鍒濆鍖栧畬鎴愬悗鍐嶆挱鏀�
+		if (isInitializing)
+		{
+			pendingAnimationName = motionName;
+			pendingAnimationLoop = loop;
+			pendingAnimationReplay = replay;
+			return null;
+		}
+		
+		if (spineAnimationState == null) 
+		{
+			Debug.LogWarning("spineAnimationState is null, cannot play animation: " + motionName);
+			return null;
+		}
 
 		if (GetCurrentAnimationName() == motionName && !replay)
 			return null;
 
 		// 鐩存帴浣跨敤 ToString() 鑰屼笉鏄皟鐢� GetAnimationName
-		return spineAnimationState.SetAnimation(0, motionName.ToString(), loop);
+		try
+		{
+			return spineAnimationState.SetAnimation(0, motionName.ToString(), loop);
+		}
+		catch (System.Exception e)
+		{
+			Debug.LogError("鎾斁鍔ㄧ敾澶辫触: " + motionName + ", 閿欒: " + e.Message);
+			return null;
+		}
 	}
 
 	// 鎾斁绗竴涓姩鐢伙紙浣滀负榛樿鍔ㄧ敾锛�
 	string GetFistSpineAnim()
 	{
+		if (skeletonGraphic == null || skeletonGraphic.Skeleton == null)
+		{
+			Debug.LogWarning("skeletonGraphic or Skeleton is null, cannot get first animation");
+			return "idle"; // 杩斿洖榛樿鍔ㄧ敾鍚嶇О
+		}
+		
 		var skeletonData = skeletonGraphic.Skeleton.Data;
 		if (skeletonData.Animations.Count > 0)
 		{
@@ -198,7 +245,7 @@
 		{
 			Debug.LogError("Spine 鏁版嵁涓病鏈夋壘鍒颁换浣曞姩鐢伙紒姝﹀皢鐨偆锛�" + skinID);
 		}
-		return "";
+		return "idle"; // 杩斿洖榛樿鍔ㄧ敾鍚嶇О
 	}
 
 	/// <summary>
@@ -227,13 +274,33 @@
 	//瓒婂ぇ瓒婂揩
 	public void SetSpeed(float speed)
 	{
+		// 濡傛灉姝e湪鍒濆鍖栦腑锛屼繚瀛橀�熷害鍙傛暟锛岀瓑寰呭垵濮嬪寲瀹屾垚鍚庡啀璁剧疆
+		if (isInitializing)
+		{
+			pendingSpeed = speed;
+			return;
+		}
+		
+		if (spineAnimationState == null)
+		{
+			Debug.LogWarning("spineAnimationState is null, cannot set speed");
+			return;
+		}
 		spineAnimationState.TimeScale = speed;
 	}
 
 	public void SetEnabled(bool isEnable)
 	{
+		// 濡傛灉姝e湪鍒濆鍖栦腑锛屼繚瀛樺惎鐢ㄧ姸鎬侊紝绛夊緟鍒濆鍖栧畬鎴愬悗鍐嶈缃�
+		if (isInitializing)
+		{
+			pendingEnabled = isEnable;
+			return;
+		}
+		
 		if (skeletonGraphic == null)
 		{
+			Debug.LogWarning("skeletonGraphic is null, cannot set enabled state");
 			return;
 		}
 		skeletonGraphic.enabled = isEnable;
@@ -241,10 +308,191 @@
 
 	public void SetGray()
 	{
+		// 濡傛灉姝e湪鍒濆鍖栦腑锛屾爣璁伴渶瑕佽缃伆搴︼紝绛夊緟鍒濆鍖栧畬鎴愬悗鍐嶈缃�
+		if (isInitializing)
+		{
+			pendingGray = true;
+			return;
+		}
+		
+		if (skeletonGraphic == null)
+		{
+			Debug.LogWarning("skeletonGraphic is null, cannot set gray material");
+			return;
+		}
 		skeletonGraphic.material = MaterialUtility.GetDefaultSpriteGrayMaterial();
 	}
 	public void SetMaterialNone()
 	{
+		// 濡傛灉姝e湪鍒濆鍖栦腑锛屾爣璁伴渶瑕佽缃棤鏉愯川锛岀瓑寰呭垵濮嬪寲瀹屾垚鍚庡啀璁剧疆
+		if (isInitializing)
+		{
+			pendingGray = false;
+			return;
+		}
+		
+		if (skeletonGraphic == null)
+		{
+			Debug.LogWarning("skeletonGraphic is null, cannot set material to none");
+			return;
+		}
 		skeletonGraphic.material = null;
 	}
+
+	/// <summary>
+	/// 寤惰繜鍒濆鍖栵紝閬垮厤鎵归噺鍒涘缓鏃跺崱椤� - 浣跨敤 UniTask
+	/// </summary>
+	private async UniTaskVoid DelayedInitializeAsync(HeroSkinConfig skinConfig, string motionName)
+	{
+		isInitializing = true;
+
+		try
+		{
+			// 澧炲姞褰撳墠鍒濆鍖栬鏁板櫒
+			int currentIndex;
+			lock (initializationLock)
+			{
+				currentIndex = activeInitializationCount++;
+			}
+
+			// 鏍规嵁褰撳墠鍒濆鍖栧簭鍙疯绠楀欢杩熸椂闂�
+			// 绗竴涓崱鐗囧欢杩�1甯э紝绗簩涓欢杩�2甯э紝浠ユ绫绘帹锛屾渶澶氬欢杩�10甯�
+			int delayFrames = Mathf.Min(currentIndex + 2, 80);
+
+			for (int i = 0; i < delayFrames; i++)
+			{
+				await UniTask.NextFrame();
+			}
+
+			skeletonGraphic.initialSkinName = skinConfig.InitialSkinName;
+			skeletonGraphic.Initialize(true);
+
+			// 鍒濆鍖栧畬鎴愬悗璁剧疆鐨偆
+			if (!string.IsNullOrEmpty(skinConfig.InitialSkinName))
+			{
+				var skeleton = skeletonGraphic.Skeleton;
+				skeleton.SetSkin(skinConfig.InitialSkinName);
+				skeleton.SetSlotsToSetupPose();
+				skeletonGraphic.Update(0);
+			}
+
+
+			spineAnimationState = skeletonGraphic.AnimationState;
+			spineAnimationState.Data.DefaultMix = 0f;
+			
+			// 鍒濆鍖栧畬鎴愬悗鎵嶆樉绀烘ā鍨�
+			skeletonGraphic.enabled = pendingEnabled;
+			
+			if (pendingGray)
+			{
+				skeletonGraphic.material = MaterialUtility.GetDefaultSpriteGrayMaterial();
+			}
+			else
+			{
+				skeletonGraphic.material = null;
+			}
+			
+			// 妫�鏌ユ槸鍚︽湁寰呰缃殑閫熷害锛屽鏋滄湁鍒欒缃�
+			if (pendingSpeed.HasValue)
+			{
+				spineAnimationState.TimeScale = pendingSpeed.Value;
+				pendingSpeed = null; // 娓呴櫎寰呰缃�熷害
+			}
+			
+			// 妫�鏌ユ槸鍚︽湁寰呮挱鏀剧殑鍔ㄧ敾锛屽鏋滄湁鍒欎紭鍏堟挱鏀惧閮ㄨ皟鐢ㄧ殑鍔ㄧ敾
+			if (!string.IsNullOrEmpty(pendingAnimationName))
+			{
+				// 涓存椂璁剧疆isInitializing涓篺alse锛屼互渚縋layAnimation鑳芥甯告挱鏀�
+				isInitializing = false;
+				PlayAnimation(pendingAnimationName, pendingAnimationLoop, pendingAnimationReplay);
+				// 娓呴櫎鎵�鏈夊緟鎾斁鍔ㄧ敾鍙傛暟
+				pendingAnimationName = null;
+				pendingAnimationLoop = false;
+				pendingAnimationReplay = true;
+			}
+			else
+			{
+				// 濡傛灉娌℃湁澶栭儴璋冪敤鐨勫姩鐢伙紝鎾斁榛樿鍔ㄧ敾
+				if (motionName == "")
+					motionName = GetFistSpineAnim();
+				
+				// 涓存椂璁剧疆isInitializing涓篺alse锛屼互渚縋layAnimation鑳芥甯告挱鏀�
+				isInitializing = false;
+				PlayAnimation(motionName, true);
+			}
+			
+			spineAnimationState.Complete -= OnAnimationComplete;
+			spineAnimationState.Complete += OnAnimationComplete;
+
+			isInitialized = true;
+			isInitializing = false;
+		}
+		catch (System.OperationCanceledException)
+		{
+			// 浠诲姟琚彇娑堬紝姝e父澶勭悊
+			isInitializing = false;
+		}
+		finally
+		{
+			// 鍑忓皯褰撳墠鍒濆鍖栬鏁板櫒
+			lock (initializationLock)
+			{
+				activeInitializationCount--;
+			}
+		}
+	}
+
+	/// <summary>
+	/// 寮哄埗绔嬪嵆鍒濆鍖栵紙鐢ㄤ簬鐗规畩鎯呭喌锛�
+	/// </summary>
+	public void ForceInitialize(string motionName = "idle")
+	{
+		if (isInitializing)
+		{
+			// 璁剧疆鏍囧織浣嶅彇娑堜箣鍓嶇殑寮傛浠诲姟
+			isInitializing = false;
+		}
+
+		var skinConfig = HeroSkinConfig.Get(skinID);
+		if (skinConfig != null && skeletonGraphic != null)
+		{
+			skeletonGraphic.initialSkinName = skinConfig.InitialSkinName;
+			skeletonGraphic.Initialize(true);
+			
+			if (!string.IsNullOrEmpty(skinConfig.InitialSkinName))
+			{
+				var skeleton = skeletonGraphic.Skeleton;
+				skeleton.SetSkin(skinConfig.InitialSkinName);
+				skeleton.SetSlotsToSetupPose();
+				skeletonGraphic.Update(0);
+			}
+
+			skeletonGraphic.enabled = true;
+			SetMaterialNone();
+
+			spineAnimationState = skeletonGraphic.AnimationState;
+			if (spineAnimationState != null)
+			{
+				spineAnimationState.Data.DefaultMix = 0f;
+				if (string.IsNullOrEmpty(motionName))
+					motionName = GetFistSpineAnim();
+				PlayAnimation(motionName, true);
+				spineAnimationState.Complete -= OnAnimationComplete;
+				spineAnimationState.Complete += OnAnimationComplete;
+			}
+
+			isInitialized = true;
+			isInitializing = false;
+		}
+	}
+
+
+
+	/// <summary>
+	/// 妫�鏌ユ槸鍚﹀凡瀹屾垚鍒濆鍖�
+	/// </summary>
+	public bool IsInitialized()
+	{
+		return isInitialized && !isInitializing;
+	}
 }
\ No newline at end of file

--
Gitblit v1.8.0