| | |
| | | |
| | | onComplete = _onComplete; |
| | | |
| | | // 立绘需要立即显示,其他情况延迟初始化 |
| | | if (isLh) |
| | | { |
| | | // 取消之前的异步任务 |
| | | CancelLoadTask(); |
| | | // 立绘立即初始化 |
| | | ForceInitialize(motionName); |
| | | } |
| | | else |
| | | { |
| | | // 取消之前的异步任务,避免多次调用导致错乱 |
| | | CancelLoadTask(); |
| | | // 创建新的取消令牌 |
| | | loadCancellationToken = new CancellationTokenSource(); |
| | | // 使用 UniTask 进行异步初始化,将instanceGO创建和资源加载都移到异步处理 |
| | | DelayedInitializeAsync(skinConfig, motionName, loadCancellationToken.Token).Forget(); |
| | | } |
| | | |
| | | // 取消之前的异步任务,避免多次调用导致错乱 |
| | | CancelLoadTask(); |
| | | // 创建新的取消令牌 |
| | | loadCancellationToken = new CancellationTokenSource(); |
| | | // 使用 UniTask 进行异步初始化,将instanceGO创建和资源加载都移到异步处理 |
| | | DelayedInitializeAsync(skinConfig, motionName, isLh, loadCancellationToken.Token).Forget(); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// 1. 资源加载使用真正的异步(LoadAssetAsync) |
| | | /// 2. skeletonGraphic.Initialize() 前进行分帧延迟,避免主线程卡顿 |
| | | /// </summary> |
| | | private async UniTaskVoid DelayedInitializeAsync(HeroSkinConfig skinConfig, string motionName, CancellationToken cancellationToken) |
| | | private async UniTaskVoid DelayedInitializeAsync(HeroSkinConfig skinConfig, string motionName, bool isLh, CancellationToken cancellationToken) |
| | | { |
| | | isInitializing = true; |
| | | |
| | |
| | | await AcquireLoadSlotAsync(cancellationToken); |
| | | |
| | | // 异步创建instanceGO和加载资源(真正的异步,不阻塞) |
| | | await CreateInstanceAndLoadAssetsAsync(skinConfig, isLh: false, cancellationToken); |
| | | await CreateInstanceAndLoadAssetsAsync(skinConfig, isLh, cancellationToken); |
| | | |
| | | // 获取当前序号用于分帧延迟 |
| | | int myOrder; |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 强制立即初始化(用于特殊情况) |
| | | /// </summary> |
| | | public void ForceInitialize(string motionName = "idle") |
| | | { |
| | | if (isInitializing) |
| | | { |
| | | // 设置标志位取消之前的异步任务 |
| | | isInitializing = false; |
| | | } |
| | | |
| | | var skinConfig = HeroSkinConfig.Get(skinID); |
| | | if (skinConfig != null) |
| | | { |
| | | // 同步创建instanceGO和加载资源(立绘需要立即显示) |
| | | CreateInstanceAndLoadAssetsSync(skinConfig, isLh: true); |
| | | |
| | | if (skeletonGraphic != null && skeletonGraphic.skeletonDataAsset != 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> |
| | | /// 同步创建instanceGO和加载资源(用于立绘) |
| | | /// </summary> |
| | | private void CreateInstanceAndLoadAssetsSync(HeroSkinConfig skinConfig, bool isLh) |
| | | { |
| | | // 确保transform处于激活状态 |
| | | if (!transform.gameObject.activeSelf) |
| | | { |
| | | transform.SetActive(true); |
| | | } |
| | | |
| | | // 创建pool和instanceGO |
| | | pool = GameObjectPoolManager.Instance.GetPool(UILoader.LoadPrefab("UIHero")); |
| | | |
| | | if (instanceGO == null) |
| | | { |
| | | instanceGO = pool.Request(); |
| | | instanceGO.transform.SetParent(transform); |
| | | //transform 的Pivot Y是0,让instanceGO 居中 |
| | | instanceGO.transform.localPosition = new Vector3(0, instanceGO.GetComponent<RectTransform>().sizeDelta.y * 0.5f); |
| | | instanceGO.transform.localScale = Vector3.one; |
| | | instanceGO.transform.localRotation = Quaternion.identity; |
| | | } |
| | | |
| | | skeletonGraphic = instanceGO.GetComponentInChildren<SkeletonGraphic>(true); |
| | | |
| | | // 同步加载资源 |
| | | if (isLh) |
| | | { |
| | | skeletonGraphic.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("Hero/SpineRes/", skinConfig.Tachie); |
| | | } |
| | | else |
| | | { |
| | | skeletonGraphic.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("Hero/SpineRes/", skinConfig.SpineRes); |
| | | } |
| | | |
| | | if (skeletonGraphic.skeletonDataAsset == null) |
| | | { |
| | | transform.SetActive(false); |
| | | if (pool != null) |
| | | pool.Release(instanceGO); |
| | | skeletonGraphic = null; |
| | | Destroy(instanceGO); |
| | | Debug.LogError("未配置spine"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 异步创建instanceGO和加载资源(用于非立绘) |