import { _decorator, Component, Node, Sprite, director, SpriteFrame, sp, AssetManager, Asset, assetManager, isValid } from 'cc'; import { GBundle } from '../game/ConfigRes'; const { ccclass, property } = _decorator; /**加载 加载动画 皮肤的组件*/ @ccclass('lLoadSpine') export class lLoadSpine extends Component { @property(sp.Skeleton) kaichangSpine: sp.Skeleton = null; @property(sp.Skeleton) zhuizhuSpine: sp.Skeleton = null; path: string = ""; key: string = ""; animation: string = "开场动画"; skinName: string = "默认皮肤"; langSp: sp.Skeleton = null; curentSpineData: sp.SkeletonData = null; /** 已成功加载并挂上的资源路径,用于同皮肤重复进入时跳过后台 load */ private _lastLoadedAssetPath: string = ''; private isLoading: boolean = false; // ✅ 添加加载锁 private abortController: { aborted: boolean } = null; // ✅ 添加取消机制 onLoad() { this.langSp = this.getComponent(sp.Skeleton); } onEnable() { this.updateLang(); } onDisable() { if (this.abortController) { this.abortController.aborted = true; } } onDestroy() { if (this.abortController) { this.abortController.aborted = true; } if (this.curentSpineData && isValid(this.curentSpineData)) { this.curentSpineData.decRef(); this.curentSpineData = null; } this._lastLoadedAssetPath = ''; } /** 与 load 时一致的 Spine 资源相对路径(不含扩展名) */ private getAssetPath(): string { const k = this.key || this.node.name; return `${k}/${this.path}`; } updateLang() { if (!this.node.isValid || this.langSp == null) return; const assetPath = this.getAssetPath(); if ( this._lastLoadedAssetPath === assetPath && this.curentSpineData && isValid(this.curentSpineData) && this.langSp.skeletonData === this.curentSpineData ) { // console.log("spineAsset 已加载", this.path, this.key); return; } if (this.abortController) { this.abortController.aborted = true; } this.abortController = { aborted: false }; if (this.isLoading) return; this.isLoading = true; const currentAbort = this.abortController; const bundleName = GBundle.Comm; const loop = this.langSp.loop; // console.log("更新 lLoadSpine 组件", this.path, this.key); this.loadBundle(bundleName).then((bundle) => { if (currentAbort.aborted || !this.node.isValid) { this.isLoading = false; return null; } if (!bundle) { this.isLoading = false; return null; } return this.loadRes(bundle, assetPath, sp.SkeletonData); }).then((spineAsset) => { if (!spineAsset) return; if (currentAbort.aborted || !this.node.isValid) { this._releaseOrphanSpineAsset(spineAsset as sp.SkeletonData); this.isLoading = false; return; } const data = spineAsset as sp.SkeletonData; if (this.curentSpineData == data) { assetManager.releaseAsset(data); this._lastLoadedAssetPath = assetPath; this.isLoading = false; return; } const oldres = this.curentSpineData; this.curentSpineData = data; data.addRef(); this._lastLoadedAssetPath = assetPath; // console.log("spineAsset 加载完成", this.path, this.key); this.langSp.clearTrack(0); this.langSp.skeletonData = data; if (this.node.isValid && this.animation) { this.langSp.setSkin(this.skinName); this.langSp.setAnimation(0, this.animation, loop); this.kaichangSpine.setAnimation(0, '开场动画', loop); this.zhuizhuSpine.setAnimation(0, '怪物追逐', loop); } if (oldres && oldres != data) { this.scheduleOnce(() => { if (oldres.refCount > 0) { oldres.decRef(); } }, 0.1); } this.isLoading = false; }).catch((error) => { // console.log("更新 lLoadSpine 组件失败", error); this.isLoading = false; }); } setKey(key: string) { this.key = key; this.updateLang(); } setPath(path: string) { this.path = path; this.updateLang(); } private _releaseOrphanSpineAsset(spineAsset: sp.SkeletonData | null): void { if (!spineAsset || spineAsset === this.curentSpineData) return; assetManager.releaseAsset(spineAsset); } private loadBundle(bundleName) { return new Promise((resolve, reject) => { let bundle = assetManager.getBundle(bundleName); if (bundle) { resolve(bundle); return; } assetManager.loadBundle(bundleName, (err, bundle) => { if (err) { // console.log(`加载Bundle:${bundleName}错误`, err); resolve(null); } else { resolve(bundle); } }) }) } private loadRes(bundle: AssetManager.Bundle, assetPath, type = Asset) { return new Promise((resolve, reject) => { bundle.load(assetPath, type, (err, asset) => { if (err) { // console.log(`加载Bundle:${bundle.name},path:${assetPath}资源错误`, err); resolve(null); } else { resolve(asset); } }); }); } }