From b97398002c77755882ecb8f5d6dcb0db98970f0f Mon Sep 17 00:00:00 2001
From: hch <305670599@qq.com>
Date: 星期一, 23 三月 2026 15:10:05 +0800
Subject: [PATCH] 0312 武将加载优化
---
Main/System/Hero/UIHeroController.cs | 187 +++++++++++++++++++++++++++++++++-------------
1 files changed, 134 insertions(+), 53 deletions(-)
diff --git a/Main/System/Hero/UIHeroController.cs b/Main/System/Hero/UIHeroController.cs
index 70b6fa8..86c5c2b 100644
--- a/Main/System/Hero/UIHeroController.cs
+++ b/Main/System/Hero/UIHeroController.cs
@@ -1,5 +1,6 @@
using System;
+using System.Threading;
using Spine;
using Spine.Unity;
using UnityEngine;
@@ -16,8 +17,14 @@
private GameObject instanceGO;
private bool isInitializing = false;
private bool isInitialized = false;
- private static int activeInitializationCount = 0; // 褰撳墠姝e湪鍒濆鍖栫殑鍗$墖鏁伴噺
- private static readonly object initializationLock = new object();
+ private CancellationTokenSource loadCancellationToken; // 鐢ㄤ簬鍙栨秷涔嬪墠鐨勫姞杞戒换鍔�
+
+ // 浣跨敤 UniTask 鎻愪緵鐨勫苟鍙戞帶鍒� - 鏀寔 WebGL
+ // 闄愬埗鍚屾椂鍔犺浇鐨勮祫婧愭暟閲忥紙榛樿涓�4锛屽彲鏍规嵁璁惧鎬ц兘璋冩暣锛�
+ private const int MAX_CONCURRENT_LOADS = 4;
+ private static int currentLoadingCount = 0;
+ private static readonly object loadLock = new object();
+ private static int initializationOrder = 0; // 鐢ㄤ簬鍒嗗抚寤惰繜鐨勫簭鍙�
public Action onComplete;
public void Create(int _skinID, float scale = 0.8f, Action _onComplete = null, string motionName = "idle", bool isLh = false)
@@ -99,17 +106,35 @@
}
onComplete = _onComplete;
-
+
// 绔嬬粯闇�瑕佺珛鍗虫樉绀猴紝鍏朵粬鎯呭喌寤惰繜鍒濆鍖�
if (isLh)
{
+ // 鍙栨秷涔嬪墠鐨勫紓姝ヤ换鍔�
+ CancelLoadTask();
// 绔嬬粯绔嬪嵆鍒濆鍖�
ForceInitialize(motionName);
}
else
{
+ // 鍙栨秷涔嬪墠鐨勫紓姝ヤ换鍔★紝閬垮厤澶氭璋冪敤瀵艰嚧閿欎贡
+ CancelLoadTask();
+ // 鍒涘缓鏂扮殑鍙栨秷浠ょ墝
+ loadCancellationToken = new CancellationTokenSource();
// 浣跨敤 UniTask 杩涜寮傛鍒濆鍖栵紝灏唅nstanceGO鍒涘缓鍜岃祫婧愬姞杞介兘绉诲埌寮傛澶勭悊
- DelayedInitializeAsync(skinConfig, motionName).Forget();
+ DelayedInitializeAsync(skinConfig, motionName, loadCancellationToken.Token).Forget();
+ }
+ }
+
+ /// <summary>
+ /// 鍙栨秷涔嬪墠鐨勫姞杞戒换鍔�
+ /// </summary>
+ private void CancelLoadTask()
+ {
+ if (loadCancellationToken != null && !loadCancellationToken.IsCancellationRequested)
+ {
+ loadCancellationToken.Cancel();
+ loadCancellationToken.Dispose();
}
}
@@ -126,6 +151,9 @@
protected void OnDestroy()
{
+ // 鍙栨秷姝e湪杩涜鐨勫姞杞戒换鍔�
+ CancelLoadTask();
+
if (spineAnimationState != null)
{
spineAnimationState.Complete -= OnAnimationComplete;
@@ -294,40 +322,58 @@
}
/// <summary>
- /// 寤惰繜鍒濆鍖栵紝閬垮厤鎵归噺鍒涘缓鏃跺崱椤� - 浣跨敤 UniTask
+ /// 寤惰繜鍒濆鍖栵紝缁撳悎骞跺彂鎺у埗鍜屽垎甯у欢杩�
+ /// 1. 璧勬簮鍔犺浇浣跨敤鐪熸鐨勫紓姝ワ紙LoadAssetAsync锛�
+ /// 2. skeletonGraphic.Initialize() 鍓嶈繘琛屽垎甯у欢杩燂紝閬垮厤涓荤嚎绋嬪崱椤�
/// </summary>
- private async UniTaskVoid DelayedInitializeAsync(HeroSkinConfig skinConfig, string motionName)
+ private async UniTaskVoid DelayedInitializeAsync(HeroSkinConfig skinConfig, string motionName, CancellationToken cancellationToken)
{
isInitializing = true;
try
{
- // 澧炲姞褰撳墠鍒濆鍖栬鏁板櫒
- int currentIndex;
- lock (initializationLock)
+ // 妫�鏌ユ槸鍚﹀凡琚彇娑�
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // 鑾峰彇鍔犺浇淇″彿閲� - 闄愬埗骞跺彂鏁帮紝閬垮厤璧勬簮绔炰簤
+ await AcquireLoadSlotAsync(cancellationToken);
+
+ // 寮傛鍒涘缓instanceGO鍜屽姞杞借祫婧愶紙鐪熸鐨勫紓姝ワ紝涓嶉樆濉烇級
+ await CreateInstanceAndLoadAssetsAsync(skinConfig, isLh: false, cancellationToken);
+
+ // 鑾峰彇褰撳墠搴忓彿鐢ㄤ簬鍒嗗抚寤惰繜
+ int myOrder;
+ lock (loadLock)
{
- currentIndex = activeInitializationCount++;
+ myOrder = initializationOrder++;
}
- // 鏍规嵁褰撳墠鍒濆鍖栧簭鍙疯绠楀欢杩熸椂闂�
- int delayFrames = Mathf.Min(currentIndex*2, 60);
+ // 鍐嶆妫�鏌ユ槸鍚﹀凡琚彇娑�
+ cancellationToken.ThrowIfCancellationRequested();
- for (int i = 0; i < delayFrames; i++)
- {
- await UniTask.NextFrame();
- }
+ // 鍦� skeletonGraphic.Initialize() 鍓嶈繘琛屽垎甯у欢杩�
+ // 鏍规嵁 MAX_CONCURRENT_LOADS 璋冩暣寤惰繜锛岄伩鍏嶆墍鏈夊璞″悓鏃舵墽琛� Initialize
+ int delayFrames = (myOrder % MAX_CONCURRENT_LOADS);
+ if (delayFrames > 0)
+ {
+ for (int i = 0; i < delayFrames; i++)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ await UniTask.NextFrame(cancellationToken);
+ }
+ }
- // 寮傛鍒涘缓instanceGO鍜屽姞杞借祫婧�
- await CreateInstanceAndLoadAssetsAsync(skinConfig, isLh: false);
+ // 鍐嶆妫�鏌ユ槸鍚﹀凡琚彇娑堬紙鍙兘鍦ㄥ欢杩熸湡闂磋鍙栨秷锛�
+ cancellationToken.ThrowIfCancellationRequested();
- if (skeletonGraphic == null || skeletonGraphic.skeletonDataAsset == null)
- {
- Debug.LogError("璧勬簮鍔犺浇澶辫触锛屾棤娉曞垵濮嬪寲妯″瀷");
- return;
- }
+ if (skeletonGraphic == null || skeletonGraphic.skeletonDataAsset == null)
+ {
+ Debug.LogError("璧勬簮鍔犺浇澶辫触锛屾棤娉曞垵濮嬪寲妯″瀷");
+ return;
+ }
- skeletonGraphic.initialSkinName = skinConfig.InitialSkinName;
- skeletonGraphic.Initialize(true);
+ skeletonGraphic.initialSkinName = skinConfig.InitialSkinName;
+ skeletonGraphic.Initialize(true);
// 鍒濆鍖栧畬鎴愬悗璁剧疆鐨偆
if (!string.IsNullOrEmpty(skinConfig.InitialSkinName))
@@ -338,13 +384,12 @@
skeletonGraphic.Update(0);
}
-
spineAnimationState = skeletonGraphic.AnimationState;
spineAnimationState.Data.DefaultMix = 0f;
-
+
// 鍒濆鍖栧畬鎴愬悗鎵嶆樉绀烘ā鍨�
skeletonGraphic.enabled = pendingEnabled;
-
+
if (pendingGray)
{
skeletonGraphic.material = MaterialUtility.GetDefaultSpriteGrayMaterial();
@@ -353,18 +398,17 @@
{
skeletonGraphic.material = null;
}
-
+
// 妫�鏌ユ槸鍚︽湁寰呰缃殑閫熷害锛屽鏋滄湁鍒欒缃�
if (pendingSpeed.HasValue)
{
spineAnimationState.TimeScale = pendingSpeed.Value;
- pendingSpeed = null; // 娓呴櫎寰呰缃�熷害
+ pendingSpeed = null;
}
-
+
// 妫�鏌ユ槸鍚︽湁寰呮挱鏀剧殑鍔ㄧ敾锛屽鏋滄湁鍒欎紭鍏堟挱鏀惧閮ㄨ皟鐢ㄧ殑鍔ㄧ敾
if (!string.IsNullOrEmpty(pendingAnimationName))
{
- // 涓存椂璁剧疆isInitializing涓篺alse锛屼互渚縋layAnimation鑳芥甯告挱鏀�
isInitializing = false;
PlayAnimation(pendingAnimationName, pendingAnimationLoop, pendingAnimationReplay);
// 娓呴櫎鎵�鏈夊緟鎾斁鍔ㄧ敾鍙傛暟
@@ -377,12 +421,11 @@
// 濡傛灉娌℃湁澶栭儴璋冪敤鐨勫姩鐢伙紝鎾斁榛樿鍔ㄧ敾
if (motionName == "")
motionName = GetFistSpineAnim();
-
- // 涓存椂璁剧疆isInitializing涓篺alse锛屼互渚縋layAnimation鑳芥甯告挱鏀�
+
isInitializing = false;
PlayAnimation(motionName, true);
}
-
+
spineAnimationState.Complete -= OnAnimationComplete;
spineAnimationState.Complete += OnAnimationComplete;
@@ -391,16 +434,52 @@
}
catch (System.OperationCanceledException)
{
- // 浠诲姟琚彇娑堬紝姝e父澶勭悊
+ // 浠诲姟琚彇娑堬紝姝e父杩斿洖
+ isInitializing = false;
+ }
+ catch (System.Exception e)
+ {
+ Debug.LogError($"鑻遍泟鍒濆鍖栧紓甯�: {e.Message}");
isInitializing = false;
}
finally
{
- // 鍑忓皯褰撳墠鍒濆鍖栬鏁板櫒
- lock (initializationLock)
+ // 閲婃斁鍔犺浇妲戒綅
+ ReleaseLoadSlot();
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇鍔犺浇妲戒綅锛堟敮鎸� WebGL 鐨勫苟鍙戞帶鍒讹級
+ /// </summary>
+ private async UniTask AcquireLoadSlotAsync(CancellationToken cancellationToken)
+ {
+ while (true)
+ {
+ // 妫�鏌ユ槸鍚﹀凡琚彇娑�
+ cancellationToken.ThrowIfCancellationRequested();
+
+ lock (loadLock)
{
- activeInitializationCount--;
+ if (currentLoadingCount < MAX_CONCURRENT_LOADS)
+ {
+ currentLoadingCount++;
+ return;
+ }
}
+ // 濡傛灉宸茶揪鍒版渶澶у苟鍙戞暟锛岀瓑寰呬笅涓�甯у啀璇�
+ await UniTask.NextFrame(cancellationToken);
+ }
+ }
+
+ /// <summary>
+ /// 閲婃斁鍔犺浇妲戒綅
+ /// </summary>
+ private void ReleaseLoadSlot()
+ {
+ lock (loadLock)
+ {
+ currentLoadingCount--;
}
}
@@ -503,8 +582,9 @@
/// <summary>
/// 寮傛鍒涘缓instanceGO鍜屽姞杞借祫婧愶紙鐢ㄤ簬闈炵珛缁橈級
+ /// 浣跨敤鐪熸鐨勫紓姝ュ姞杞斤紝涓嶉樆濉炰富绾跨▼
/// </summary>
- private async UniTask CreateInstanceAndLoadAssetsAsync(HeroSkinConfig skinConfig, bool isLh)
+ private async UniTask CreateInstanceAndLoadAssetsAsync(HeroSkinConfig skinConfig, bool isLh, CancellationToken cancellationToken)
{
// 纭繚transform澶勪簬婵�娲荤姸鎬�
if (!transform.gameObject.activeSelf)
@@ -512,9 +592,12 @@
transform.SetActive(true);
}
+ // 妫�鏌ユ槸鍚﹀凡琚彇娑�
+ cancellationToken.ThrowIfCancellationRequested();
+
// 鍒涘缓pool鍜宨nstanceGO
pool = GameObjectPoolManager.Instance.GetPool(UILoader.LoadPrefab("UIHero"));
-
+
if (instanceGO == null)
{
instanceGO = pool.Request();
@@ -526,21 +609,19 @@
}
skeletonGraphic = instanceGO.GetComponentInChildren<SkeletonGraphic>(true);
-
- // 鍦ㄤ富绾跨▼涓姞杞借祫婧愶紝閬垮厤Unity API绾跨▼瀹夊叏闂
- // 浣跨敤UniTask.Yield()鏉ョ‘淇濆湪涓荤嚎绋嬩腑鎵ц
- await UniTask.Yield();
-
- if (isLh)
+
+ // 鐪熸鐨勫紓姝ュ姞杞借祫婧� - 涓嶉樆濉炰富绾跨▼
+ string assetName = isLh ? skinConfig.Tachie : skinConfig.SpineRes;
+ SkeletonDataAsset loadedAsset = await ResManager.Instance.LoadAssetAsync<SkeletonDataAsset>("Hero/SpineRes/", assetName);
+
+ // 鍐嶆妫�鏌ユ槸鍚﹀凡琚彇娑�
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (loadedAsset != null)
{
- skeletonGraphic.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("Hero/SpineRes/", skinConfig.Tachie);
+ skeletonGraphic.skeletonDataAsset = loadedAsset;
}
else
- {
- skeletonGraphic.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("Hero/SpineRes/", skinConfig.SpineRes);
- }
-
- if (skeletonGraphic.skeletonDataAsset == null)
{
transform.SetActive(false);
if (pool != null)
--
Gitblit v1.8.0