using System; using Cysharp.Threading.Tasks; #if Immersal using Immersal.AR; #endif using Stary.Evo; using Stary.Evo.InformationSave; using UnityEngine; using UnityEngine.SceneManagement; using YooAsset; namespace Stary.Evo { public class LoadResState : AbstractFSMIStateAsync { private DomainConfig.LoadResType loadResType; public GameObject mainPrefab; private DomainConfig domainConfig; private string _sceneName; public LoadResState(IFsmSystemAsync system) : base(system) { } public override UniTask OnEnterAsync() { return UniTask.CompletedTask; } public override UniTask OnEnterAsync(T param) { return UniTask.CompletedTask; } public override async UniTask OnEnterAsync(T1 param1, T2 param2) { Debug.Log("加载资源..."); domainConfig = param1 as DomainConfig; loadResType = domainConfig.loadResType; Type type = param2 as Type; var package = YooAssets.GetPackage(domainConfig.domain); switch (loadResType) { case DomainConfig.LoadResType.Prefab: await LoadDomainPrefab(package); break; case DomainConfig.LoadResType.Scene: var sceneMode = domainConfig.loadSceneMode; var physicsMode = LocalPhysicsMode.None; SceneHandle handle = package.LoadSceneAsync(domainConfig.sceneIdentifier, sceneMode, physicsMode); await handle; Scene targetScene = SceneManager.GetSceneByName(handle.SceneName); // targetScene.name = domainConfig.mainScene; // 设置为 active scene 或者后续 Move 到该 scene SceneManager.SetActiveScene(targetScene); _sceneName = targetScene.name; mainPrefab = GameObject.Find(domainConfig.mainPrefab); if (mainPrefab == null) { await LoadDomainPrefab(package); } break; } if (domainConfig.domain != "Main") { LocalTransformInfo info = mainPrefab.GetOrAddComponent(); FsmLoadSystem fsmLoadSystem = FsmSystem as FsmLoadSystem; if (info._list.Count >= 2) { if (fsmLoadSystem.GetOpenDomainType() == OpenDomainType.PointCloud) { info.Switch(1); } else if (fsmLoadSystem.GetOpenDomainType() == OpenDomainType.VIOICE) { info.Switch(0); } else if (fsmLoadSystem.GetOpenDomainType() == OpenDomainType.ImageTracked) { info.transform.position = fsmLoadSystem.GetTransformCtor().position; info.transform.rotation = Quaternion.Euler(fsmLoadSystem.GetTransformCtor().rotation); info.transform.localScale = fsmLoadSystem.GetTransformCtor().scale; } else { info.Switch(0); } } else { Debug.LogError($"UnityEvo:{mainPrefab.name}的TransformInfo长度小于2,无法继续运行,请排查"); } } if (mainPrefab != null) { DomainBase hotfixInstance = mainPrefab.GetComponent(type) as DomainBase; if (hotfixInstance == null) { hotfixInstance = mainPrefab.AddComponent(type) as DomainBase; } hotfixInstance.DomainName = domainConfig.domain; if (hotfixInstance == null) { Debug.LogError($"热更类{type.Name}实例创建失败!必须继承MonoBehaviour"); return; } // 原有调用逻辑修改为使用实例 hotfixInstance.OnEnter(""); hotfixInstance.OnEnterAsync(""); } } public override void OnUpdate() { base.OnUpdate(); } private async UniTask LoadDomainPrefab(ResourcePackage package) { // 加载热更资源 var loadOperation = package.LoadAssetAsync(domainConfig.mainPrefab); await loadOperation; if (loadOperation.Status == EOperationStatus.Succeed) { #if Immersal ARSpace arSpace = GameObject.FindObjectOfType(); if (arSpace != null) { Debug.Log("UnityEvo:找到ARSpace,开始加载点云运行环境..."); mainPrefab = loadOperation.InstantiateSync(arSpace.transform); } else { Debug.Log("UnityEvo:未找到ARSpace,开始加载普通运行环境,通过语音唤醒..."); mainPrefab = loadOperation.InstantiateSync(); } #elif NotPointClond mainPrefab = loadOperation.InstantiateSync(); #endif if (domainConfig.domain == "Main") AppConfig.SetDefaultMainInstance(mainPrefab); } } public override async UniTask OnExitAsync() { Debug.Log("UnityEvo:Domain退出..."); if (domainConfig.domain != "Main") { DomainBase domainBase = mainPrefab.GetOrAddComponent(); if (domainBase == null) { Debug.LogError($"UnityEvo:{mainPrefab.name}的DomainBase为空,无法退出,请排查"); } else { domainBase.OnExit(); await domainBase.OnExitAsync(); } if (domainBase != null) { GameObject.Destroy(domainBase.gameObject); await ForceUnloadAllAssets(domainBase.DomainName); } if (loadResType == DomainConfig.LoadResType.Scene) { await SceneManager.UnloadSceneAsync(_sceneName); } AppConfig.PackageDomainName = ""; } } // 强制卸载所有资源包,该方法请在合适的时机调用。 // 注意:Package在销毁的时候也会自动调用该方法。 private async UniTask ForceUnloadAllAssets(string packageName) { var package = YooAssets.TryGetPackage(packageName); if (package != null) { var operation = package.UnloadAllAssetsAsync(); await operation; await package.DestroyAsync(); YooAssets.RemovePackage(packageName); Resources.UnloadUnusedAssets(); GC.Collect(); GC.WaitForPendingFinalizers(); Debug.Log($"UnityEvo:{packageName} 资源包已卸载..."); } else { Debug.LogWarning($"UnityEvo:{packageName} 资源包不存在,请检查是否已经卸载还是卸载异常..."); } } } }