// ReSharper restore InconsistentNaming public PoolBossItem Clone() { var clone = new PoolBossItem { prefabSource = prefabSource, prefabTransform = prefabTransform, instancesToPreload = instancesToPreload, isExpanded = isExpanded, logMessages = logMessages, allowInstantiateMore = allowInstantiateMore, itemHardLimit = itemHardLimit, allowRecycle = allowRecycle, categoryName = categoryName, delayNavMeshEnableByFrames = delayNavMeshEnableByFrames }; #if ADDRESSABLES_ENABLED if (prefabAddressable.RuntimeKeyIsValid()) { clone.prefabAddressable = new AssetReference(prefabAddressable.RuntimeKey.ToString()); } #endif return clone; }
// ReSharper disable once MemberCanBeMadeStatic.Local private void CreatePoolItemClones(PoolBossItem item, bool isDuringAwake) { if (!isDuringAwake) Instance.poolItems.Add(item); if (item.instancesToPreload <= 0) return; switch (item.prefabSource) { case PrefabSource.Prefab: if (item.prefabTransform == null) { if (isDuringAwake) { Debug.LogError( $"You have an item in Pool Boss with no prefab assigned in category: {item.categoryName}"); } else { Debug.LogError("You are attempting to add a Pool Boss Item with no prefab assigned."); } return; } FillItemPool(item, item.prefabTransform); return; #if ADDRESSABLES_ENABLED case PrefabSource.Addressable: if (!PoolAddressableOptimizer.IsAddressableValid(item.prefabAddressable)) { if (isDuringAwake) { Debug.LogError("You have an item in Pool Boss with no prefab assigned in category: " + item.categoryName); } else { Debug.LogError("You are attempting to add a Pool Boss Item with no prefab assigned."); } return; } StartCoroutine(PoolAddressableOptimizer.LoadOrReturnTransformAsset(item, FillItemPool, AddressableFailedLoad)); return; #endif } }
/// <summary> /// This method allows you to add a new Pool Item at runtime. /// </summary> /// <param name="itemTrans">The Transform of the item.</param> /// <param name="preloadInstances">The number of instances to preload.</param> /// <param name="canInstantiateMore">Can instantiate more or not</param> /// <param name="hardLimit">Item Hard Limit</param> /// <param name="logMsgs">Log messages during spawn and despawn.</param> /// <param name="catName">Category name</param> public static void CreateNewPoolItem(Transform itemTrans, int preloadInstances, bool canInstantiateMore, int hardLimit, bool logMsgs, string catName) { var newItem = new PoolBossItem() { prefabTransform = itemTrans, instancesToPreload = preloadInstances, allowInstantiateMore = canInstantiateMore, itemHardLimit = hardLimit, isExpanded = true, logMessages = logMsgs, categoryName = catName }; if (string.IsNullOrEmpty(catName)) { newItem.categoryName = Instance._categories[0].CatName; } Instance.CreatePoolItemClones(newItem, false); }
private void FillItemPool(PoolBossItem item, Transform transformTemplate) { var itemName = GetPrefabName(transformTemplate); // calling this here will add the PoolableInfo script to the prefab, so all clones will get it. if (PoolItemsByName.ContainsKey(itemName)) { Debug.LogError($"You have more than one instance of '{itemName}' in Pool Boss. Skipping the second instance."); return; } var itemClones = new List<Transform>(); var navAgent = transformTemplate.GetComponent<NavMeshAgent>(); var hasAgent = navAgent != null; for (var i = 0; i < item.instancesToPreload; i++) { var createdObjTransform = InstantiateForPool(transformTemplate, i + 1); itemClones.Add(createdObjTransform); } var instanceList = new PoolItemInstanceList(itemClones) { LogMessages = item.logMessages, AllowInstantiateMore = item.allowInstantiateMore, SourceTrans = transformTemplate, ItemHardLimit = item.itemHardLimit, AllowRecycle = item.allowRecycle, EnableNavMeshAgent = hasAgent && item.enableNavMeshAgentOnSpawn, NavMeshAgentFrameDelay = item.delayNavMeshEnableByFrames, CategoryName = item.categoryName }; if (Instance._categories.Find(delegate (PoolBossCategory x) { return x.CatName == item.categoryName; }) == null) { Instance._categories.Add(new PoolBossCategory() { CatName = item.categoryName, IsExpanded = true, IsEditing = false }); } PoolItemsByName.Add(itemName, instanceList); }
private void ContinueInit() { if (_isReady || Time.frameCount <= _lastFramInitContinued) { return; } _lastFramInitContinued = Time.frameCount; var itemCountToStopAt = Instance.poolItems.Count; if (Instance.framesForInit != 1) { var framesInitSoFar = Time.frameCount - _initFrameStart + 1; itemCountToStopAt = (int)Math.Max(framesInitSoFar * _itemsToInitPerFrame, 0); } if (logMessages) { Debug.Log( $"Pool Boss initializing: frame #: {Time.frameCount} - creating items: {(_itemsInited + 1)} - {itemCountToStopAt}"); } PoolBossItem item = null; // ReSharper disable once ForCanBeConvertedToForeach for (var p = _itemsInited; p < itemCountToStopAt; p++) { item = Instance.poolItems[p]; Instance.CreatePoolItemClones(item, true); _itemsInited++; } if (itemCountToStopAt != Instance.poolItems.Count) { return; } if (logMessages) { Debug.Log($"Pool Boss done initializing in frame #: {Time.frameCount}"); } _isReady = true; }
private static readonly object _syncRoot = new object(); // to lock below /// <summary> /// Start Coroutine when calling this, passing in success and failure action delegates. /// </summary> /// <param name="addressable"></param> /// <param name="successAction"></param> /// <param name="failureAction"></param> /// <returns></returns> public static IEnumerator LoadOrReturnTransformAsset(PoolBossItem poolItem, System.Action <PoolBossItem, Transform> successAction, System.Action failureAction) { var addressable = poolItem.prefabAddressable; if (!IsAddressableValid(addressable)) { if (failureAction != null) { failureAction(); } yield break; } var addressableId = GetAddressableId(addressable); AsyncOperationHandle <GameObject> loadHandle; GameObject gameObjectReference; var shouldReleaseLoadedAssetNow = false; if (AddressableTasksByAddressibleId.ContainsKey(addressableId)) { loadHandle = AddressableTasksByAddressibleId[addressableId].AssetHandle; gameObjectReference = loadHandle.Result; } else { loadHandle = addressable.LoadAssetAsync <GameObject>(); while (!loadHandle.IsDone) { yield return(PoolBoss.EndOfFrameDelay); } gameObjectReference = loadHandle.Result; if (gameObjectReference == null || loadHandle.Status != AsyncOperationStatus.Succeeded) { var errorText = ""; if (loadHandle.OperationException != null) { errorText = " Exception: " + loadHandle.OperationException.Message; } Debug.LogError("Addressable file for could not be located." + errorText); if (failureAction != null) { failureAction(); } yield break; } lock (_syncRoot) { if (!AddressableTasksByAddressibleId.ContainsKey(addressableId)) { AddressableTasksByAddressibleId.Add(addressableId, new AddressableTracker <GameObject>(loadHandle)); } else { // race condition reached. Another load finished before this one. Throw this away and use the other, to release memory. shouldReleaseLoadedAssetNow = true; gameObjectReference = AddressableTasksByAddressibleId[addressableId].AssetHandle.Result; } } } if (shouldReleaseLoadedAssetNow) { Addressables.Release(loadHandle); } if (successAction != null) { successAction(poolItem, gameObjectReference.transform); } }