using BrewMonster.Scripts; using Cysharp.Threading.Tasks; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace BrewMonster { public class AddressableObject : MonoBehaviour { public string assetPath; private GameObject _instance; private bool _isLoading; private bool _isLoaded; private int _loadRequestId; public bool IsLoaded => _isLoaded; public bool IsLoading => _isLoading; // some object' position is base on the center of the mesh. So we don't need to update the position at start up. public bool NeedToUpdatePositionAtStartUp; public Vector3 ObjectPosition; public Vector3 ObjectPositionOxz; void Awake() { if (NeedToUpdatePositionAtStartUp) { ObjectPosition = transform.position; ObjectPositionOxz = new Vector3(ObjectPosition.x, 0, ObjectPosition.z); } } public async UniTask LoadAsset() { if (string.IsNullOrEmpty(assetPath)) { return; } if (_instance != null || _isLoading) { return; } _isLoading = true; int requestId = ++_loadRequestId; var model = await AddressableManager.Instance.LoadPrefabAsync(assetPath); // Object might have been destroyed while awaiting. if (this == null || gameObject == null) { return; } // If we got unloaded while loading, release the cached handle to avoid keeping RAM. if (requestId != _loadRequestId) { _isLoading = false; AddressableManager.Instance.ReleaseAsset(assetPath); return; } _isLoading = false; if (model != null && _instance == null) { _instance = Instantiate(model); var modelTransform = _instance.transform; modelTransform.SetParent(transform); modelTransform.localPosition = Vector3.zero; modelTransform.localRotation = Quaternion.identity; modelTransform.localScale = Vector3.one; _instance.SetActive(true); _isLoaded = true; } else { BMLogger.Log($"AddressableObject: LoadAsset: Object can't be load from Addressable {assetPath}"); } } public void UnloadAsset() { // make the loading request invalid. _loadRequestId++; _isLoading = false; _isLoaded = false; if (_instance != null) { if (Application.isPlaying) { Destroy(_instance); } else { DestroyImmediate(_instance); } _instance = null; } else if (transform.childCount > 0) { // Backward-compatible cleanup if older versions instantiated children without tracking. for (int i = transform.childCount - 1; i >= 0; i--) { if (Application.isPlaying) { Destroy(transform.GetChild(i).gameObject); } else { DestroyImmediate(transform.GetChild(i).gameObject); } } } if (string.IsNullOrEmpty(assetPath)) { return; } AddressableManager.Instance.ReleaseAsset(assetPath); } #if UNITY_EDITOR public static string _modelPathPrefixToRemove = "Assets/ModelRenderer/Art/Models"; [ContextMenu("Get Asset Path")] public void GetAssetPath() { var prefabObject = PrefabUtility.GetCorrespondingObjectFromSource(this.gameObject); if (prefabObject != null) { var path = AssetDatabase.GetAssetPath(prefabObject); //remove the prefix from the path path = path.Substring(_modelPathPrefixToRemove.Length + 1); //remove the .prefab suffix path = path.Substring(0, path.Length - ".prefab".Length); assetPath = path; // now delete all the children of this object while (transform.childCount > 0) { DestroyImmediate(transform.GetChild(0).gameObject); } //unpack completely the prefab PrefabUtility.UnpackPrefabInstance(this.gameObject, PrefabUnpackMode.Completely, InteractionMode.UserAction); } else { Debug.LogError("No prefab object found for this object"); } } #endif } }