/// <summary> /// Creates a new instance. /// /// If PoolManager is installed and the pre-proccessor directive is /// uncommented at the top of TargetTracker.cs, this will use PoolManager to /// pool ammo instances. /// /// If the pool doesn't exist before this is used, it will be created. /// /// Otherwise, Unity's Object.Instantiate() is used. /// </summary> /// <param name="prefab">The prefab to spawn an instance from</param> /// <param name="pos">The position to spawn the instance</param> /// <param name="rot">The rotation of the new instance</param> /// <returns></returns> public static Transform Spawn(string poolName, Transform prefab, Vector3 pos, Quaternion rot) { #if POOLMANAGER_INSTALLED || USE_OTHER_POOLING if (poolName == "") // Overload use of poolName to toggle pooling { return((Transform)Object.Instantiate(prefab, pos, rot)); } #endif #if POOLMANAGER_INSTALLED // If the pool doesn't exist, it will be created before use if (!PoolManager.Pools.ContainsKey(poolName)) { (new GameObject(poolName)).AddComponent <SpawnPool>(); } return(PoolManager.Pools[poolName].Spawn(prefab, pos, rot)); #elif USE_OTHER_POOLING InstanceManager.OnSpawnDelegates(poolName, prefab, pos, rot); #else return((Transform)Object.Instantiate(prefab, pos, rot)); #endif }
/// <summary> /// Despawns this EventTrigger on impact, timeout or sleep (depending on options) /// and notifies objects in range with EventInfo. /// </summary> public virtual IEnumerator Fire() { // Prevent being run more than once in a frame where it has already // been despawned. if (!this.gameObject.activeInHierarchy) { yield break; } if (this.duration > 0) { this.range = this.startRange; } // This TargetList collects targets that are notified below the this.detectedTargetsCache.Clear(); // Prevent the Area event from notifying targets in this.OnTargetDetectedNotify() this.blockNotifications = true; if (this.areaHit) { // This is turned back off OnDisable() (base class) // Also triggers OnDetected via an event to handle all targets found when enabled! this.setAreaColliderEnabled(true); // Need to wait a frame to let Unity send the physics Enter events to the Area. // Wait for next frame to begin to be sure targets have been propegated // This also makes this loop easier to manage. //yield return new WaitForFixedUpdate(); // This seems logical but doesn't work yield return(null); } else { this.OnNewTargetHandler(this, this.target); } // Let future detections notifiy targets (in case duration is != 0) // This HAS to be bellow the yield or it will only work sometimes. this.blockNotifications = false; // Trigger delegates BEFORE processing notifications in case a delegate modifies the // list of targets if (this.OnFireDelegates != null) { this.OnFireDelegates(this.detectedTargetsCache); } foreach (Target processedTarget in this.detectedTargetsCache) { this.HandleNotifyTarget(processedTarget); } this.detectedTargetsCache.Clear(); // Just to be clean. if (this.notifyTargets == NOTIFY_TARGET_OPTIONS.PassInfoToEventTrigger) { this.SpawnOnFirePrefab(true); } // Hnadle keeping this EventTrigger alive and the range change over time. // Any new targets from this point on will be handled by OnNewDetected, which // is triggered by AreaTargetTracker logic. if (this.duration != 0) { // Determine which while() statement is needed. One that runs out after a // certain duration or one that runs forever while this component is active. if (this.duration < 0) { while (true) { // UPDATE EVENT if (this.OnFireUpdateDelegates != null) { this.OnFireUpdateDelegates(-1); } //yield return new WaitForFixedUpdate(); // Seems logical but doesn't work. yield return(null); } } else { float timer = 0; float progress = 0; // Normalized value that will be 0-1 while (progress < 1) { // UPDATE EVENT if (this.OnFireUpdateDelegates != null) { this.OnFireUpdateDelegates(progress); } timer += Time.deltaTime; progress = timer / this.duration; this.range = this._endRange * progress; //yield return new WaitForFixedUpdate(); // Seems logical but doesn't work. yield return(null); } this.range = this._endRange; // for percision } } // // Handle despoawn... // // Do this check again due to duration. // Prevent being run more than once in a frame where it has already // been despawned. if (!this.gameObject.activeInHierarchy) { yield break; } InstanceManager.Despawn(this.poolName, this.transform); yield return(null); }
/// <summary> /// Destroys the projectile on impact and finds objects in range to /// affect if they share the same tag as target. /// </summary> public void DetonateProjectile() { // Prevent being run more than once in a frame where it has already // been destroyed. if (!this.gameObject.activeInHierarchy) { return; } // Build a new list of targets depending on the options used var targetList = new TargetList(); if (this.areaHit) { // This is turned back off OnDisable() (base class) this.perimeter.enabled = true; targetList.AddRange(this.targets); // Add all targets in range } else { if (this.target != Target.Null) { targetList.Add(this.target); // Add projectile target } } if (this.debugLevel > DEBUG_LEVELS.Off) { string msg = string.Format("Detonating with targets: {0}", targetList); Debug.Log(string.Format("Projectile ({0}): {1}", this.name, msg)); } // Create a new list of targets which have this target tracker reference. // This is for output so targets which are handled at all by this Projectile // are stamped with a reference. var targetCopies = new TargetList(); Target target; foreach (Target inTarget in targetList) { if (inTarget == Target.Null) { continue; } // Can't edit a struct in a foreach loop, so need to copy and store target = new Target(inTarget); target.projectile = this; // Add reference. null before t targetCopies.Add(target); switch (this.notifyTargets) { case NOTIFY_TARGET_OPTIONS.Direct: target.targetable.OnHit(this.effectsOnTarget, target, this.collider); break; } // Just for debug. Show a gizmo line when firing if (this.debugLevel > DEBUG_LEVELS.Off) { Debug.DrawLine ( this.xform.position, target.transform.position, Color.red ); } } switch (this.notifyTargets) { case NOTIFY_TARGET_OPTIONS.Direct: this.SpawnDetonatorPrefab(false); break; case NOTIFY_TARGET_OPTIONS.PassToDetonator: this.SpawnDetonatorPrefab(true); break; } // Trigger delegates if (this.OnDetonationDelegates != null) { this.OnDetonationDelegates(targetCopies); } // Clean-up in case this instance is used in a pooling system like PoolManager this.target = Target.Null; InstanceManager.Despawn(this.transform); }