public IEnumerator StartStage() { if (_shooter != null) { UBulletPoolManager poolManager = _shooter.GetBulletPoolManager(); // Check if the bulletIndex is in valid range (bullet exists) if (_bulletIndex >= 0 && _bulletIndex < poolManager.GetPrototypesCount()) { for (int i = 0; i < _count; i++) { UBulletObject fetchedBullet = poolManager.FetchBulletByID(_bulletIndex, true, _shouldBulletAddToMonitor, _shouldBulletActivateCollider); // rotate fetched bullet to have the same rotation as the shooter. // This is meaningful as we want bullets to shoot at the same UP direction of the shooter Transform fetchedBulletTrans = fetchedBullet.GetTransform(); Transform shooterTrans = _shooter.GetTransform(); fetchedBulletTrans.position = shooterTrans.position; fetchedBulletTrans.rotation = shooterTrans.rotation; // More motion settings on the bullet itself _bulletInitEvent.Invoke(fetchedBullet); // Invoke shootEvent here _shooter.GetActor().InvokeShootEvents(fetchedBullet); // all non-last shots should wait for the specified interval if (i < _count - 1) { yield return(new WaitForSeconds(_intervalFunc())); } } } } _isComplete = true; yield break; }
public UShootActor InvokeShootEvents(UBulletObject shotBullet) // This will be called in StartStage() in stages immediately on shoot { if (shootEvents != null) { shootEvents.Invoke(shotBullet); } return(this); }
/// <summary> /// Fetchs the bullet with ID. /// Here we will do separation of tasks /// a.k.a we will NOT worry about ANYTHING about position, rotation, etc. during fetching /// NOTICE: ALL fetched bullet would be INACTIVE at the beginning /// NOTICE: the last shouldActivateCollider is defaulted to TRUE /// </summary> /// <returns>The bullet by ID.</returns> /// <param name="id">ID.</param> public UBulletObject FetchBulletByID(int id, bool shouldActivate = false, bool shouldAddToMonitor = true, bool shouldActivateCollider = true) { Stack <UBulletObject> thePool = this.pools [id]; if (thePool.Count <= 0) { UBulletObject bulletObject = (Instantiate(this.prototypes [id].trans.gameObject) as GameObject).GetComponent <UBulletObject> (); // Setting the pool manager of the new bullet to self bulletObject.poolManager = this; // Make it a child of poolTransform bulletObject.trans.parent = poolTransform; if (shouldActivate) { // Setting recyclable to FALSE to avoid unexpected removal from colliderMonitor bulletObject.collider.SetRecyclable(false); if (shouldAddToMonitor) { collisionMonitor.AddBulletCollider(bulletObject.collider); if (shouldActivateCollider) { bulletObject.collider.SetEnable(true); } } } else { bulletObject.gameObject.SetActive(false); } // ALERT: REMOVED due to performance issue // bulletObject.trans.DOKill (); return(bulletObject); } else { UBulletObject bulletObject = this.pools [id].Pop(); if (shouldActivate) { bulletObject.gameObject.SetActive(true); // Setting recyclable to FALSE to avoid unexpected removal from colliderMonitor bulletObject.collider.SetRecyclable(false); if (shouldAddToMonitor) { collisionMonitor.AddBulletCollider(bulletObject.collider); if (shouldActivateCollider) // activate collider ONLY when the whole gameObject is first activated { bulletObject.collider.SetEnable(true); } } } // ALERT: REMOVED due to performance issue // bulletObject.trans.DOKill (); return(bulletObject); } }
/// <summary> /// Preloads the bullet by ID. /// NOTICE: ALL preloaded bullets would be INACTIVE by default /// </summary> /// <param name="id">Identifier.</param> /// <param name="count">Count.</param> public UBulletPoolManager PreloadBulletByID(int id, int count) { for (int i = 0; i < count; i++) { // This GetComponent<UBulletObject> is a must... though slow... // But since it is happened at the beginning of stage, should not be a huge problem UBulletObject bulletObject = (Instantiate(this.prototypes[id].trans.gameObject) as GameObject).GetComponent <UBulletObject>(); // Setting the pool manager of the new bullet to self bulletObject.poolManager = this; // Make it a child of poolTransform bulletObject.trans.parent = poolTransform; // Make this newly created bullet inactive bulletObject.gameObject.SetActive(false); // Push the newly created bullet to corresponding stack this.pools[id].Push(bulletObject); } return(this); }
// Moving to Awake() to avoid unexpected uninitialized bug void Awake() { this.pools = new List <Stack <UBulletObject> > (); int prototypesLen = this.prototypes.Count; for (int i = 0; i < prototypesLen; i++) { UBulletObject obj = prototypes [i]; // Set pool ID obj.poolID = i; // Insert a new pool entry pools.Add(new Stack <UBulletObject>()); } if (this.poolTransform == null) { this.poolTransform = (new GameObject("_Pool")).transform; this.poolTransform.parent = this.transform; } }
/// <summary> /// Recycles the child bullet helper. /// This is used to help recycling the children bullets /// The different from the above method is that the PUSH TO STACK is dependent on shouldSplitChildrenOnRecycle /// This takes into account of the idea that MAYBE you want to reclaim the children bullets on recycle /// while the FIRST direct call to PUSH in above method is a MUST, while children ones are NOT /// </summary> /// <param name="bulletObject">Bullet object.</param> /// <param name="shouldRecycleChildren">If set to <c>true</c> should recycle children.</param> /// <param name="shouldSplitChildrenOnRecycle">If set to <c>true</c> should split children to individual pools on recycle.</param> private void _RecycleChildBulletHelper(UBulletObject bulletObject, bool shouldRecycleChildren = false, bool shouldSplitChildrenOnRecycle = false) { // Stopping all running tweens and sequences if (isUsingDOTween) { bulletObject.KillAllDOTweenAndDOTweenSequence(); } // LEANTWEEN if (isUsingLeanTween) { bulletObject.KillAllLeanTweenAndLeanTweenSequence(); } // FIX: Terminate all callbacks (MUST DO!!!) bulletObject.actor.ClearAllCallbacks(); bulletObject.collider.SetEnable(false); // Removing current bullet collision detection is done by signaling the collisionMonitor // To avoid racing, ALWAYS setRecyclable to true in calling bulletObject.collider.SetRecyclable(true); bulletObject.gameObject.SetActive(false); if (shouldSplitChildrenOnRecycle) { this.pools [bulletObject.GetPoolID()].Push(bulletObject); } if (shouldRecycleChildren && bulletObject.children.Count >= 0) { foreach (UBulletObject childObject in bulletObject.children) { this._RecycleChildBulletHelper(childObject, shouldRecycleChildren, shouldSplitChildrenOnRecycle); } } }
public IEnumerator StartStage() { if (_shooter != null) { UBulletPoolManager poolManager = _shooter.GetBulletPoolManager(); // Check if the bulletIndex is in valid range (bullet exists) if (_bulletIndex >= 0 && _bulletIndex < poolManager.GetPrototypesCount()) { // Forever and infinite while (true) { // when this is true, the infinite call is forcefully stopped if (_isForceStopped) { break; } UBulletObject fetchedBullet = poolManager.FetchBulletByID(_bulletIndex, true, _shouldBulletAddToMonitor, _shouldBulletActivateCollider); // rotate fetched bullet to have the same rotation as the shooter. // This is meaningful as we want bullets to shoot at the same UP direction of the shooter Transform fetchedBulletTrans = fetchedBullet.GetTransform(); Transform shooterTrans = _shooter.GetTransform(); fetchedBulletTrans.position = shooterTrans.position; fetchedBulletTrans.rotation = shooterTrans.rotation; // More motion settings on the bullet itself _bulletInitEvent.Invoke(fetchedBullet); // Invoke shootEvent here _shooter.GetActor().InvokeShootEvents(fetchedBullet); yield return(new WaitForSeconds(_intervalFunc())); } } } yield break; }
public int GetPoolID(UBulletObject obj) { return(obj.GetPoolID()); }
public UBulletActor(UBulletObject obj, UBulletCollider ubc) { this.bulletObject = obj; this.collider = ubc; }