< Summary

Class:ParticleManager
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Managers/ParticleManager.cs
Covered lines:34
Uncovered lines:120
Coverable lines:154
Total lines:222
Line coverage:22% (34 of 154)
Covered branches:0
Total branches:0
Covered methods:9
Total methods:24
Method coverage:37.5% (9 of 24)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ParticleManager()0%110100%
ClearHitMarkers()0%6200%
Awake()0%3.473062.5%
Start()0%3.473062.5%
Update()0%110100%
InitializeMissileTrailParticlePool()0%6200%
InstantiateMissileTrail(...)0%2100%
InstantiateMissileTrailsOverTime()0%20400%
InitializeMissileExplosionParticlePool()0%6200%
InstantiateMissileExplosion(...)0%2100%
InstantiateMissileExplosionsOverTime()0%20400%
RegisterNewInterceptor(...)0%110100%
RegisterInterceptorHit(...)0%6200%
RegisterInterceptorMiss(...)0%2100%
RegisterNewThreat(...)0%110100%
RegisterAgentTerminated(...)0%6200%
RegisterSimulationEnded()0%2.262060%
SpawnHitMarker(...)0%2100%
PlayMissileExplosion(...)0%12300%
ReturnExplosionAfterDelay()0%12300%
ReturnMissileExplosionParticle(...)0%12300%
CommandeerAgentTrailRenderer(...)0%20400%

File(s)

/github/workspace/Assets/Scripts/Managers/ParticleManager.cs

#LineLine coverage
 1using System.Collections;
 2using System.Collections.Generic;
 3using UnityEngine;
 4
 5public class ParticleManager : MonoBehaviour {
 26  public static ParticleManager Instance { get; private set; }
 7
 8  private Queue<GameObject> _missileTrailPool;
 9  [SerializeField]
 10  private int _missileTrailPoolCount;
 11  [SerializeField]
 12  private Queue<GameObject> _missileExplosionPool;
 13  [SerializeField]
 14  private int _missileExplosionPoolCount;
 15
 16  [SerializeField]
 217  private List<TrailRenderer> _agentTrailRenderers = new List<TrailRenderer>();
 18
 19  [SerializeField, Tooltip("The material to use for commandeered interceptor trail renderers")]
 20  public Material InterceptorTrailMatFaded;
 21  [SerializeField, Tooltip("The material to use for commandeered threat trail renderers")]
 22  public Material ThreatTrailMatFaded;
 23
 24  [SerializeField]
 225  private List<GameObject> _hitMarkerList = new List<GameObject>();
 26
 027  public void ClearHitMarkers() {
 028    foreach (var hitMarker in _hitMarkerList) {
 029      Destroy(hitMarker);
 030    }
 031    _hitMarkerList.Clear();
 032  }
 33
 134  private void Awake() {
 135    if (Instance != null && Instance != this) {
 036      Destroy(gameObject);
 037      return;
 38    }
 139    Instance = this;
 140    DontDestroyOnLoad(gameObject);
 141  }
 42
 143  private void Start() {
 144    _missileTrailPool = new Queue<GameObject>();
 145    _missileExplosionPool = new Queue<GameObject>();
 146    _hitMarkerList = new List<GameObject>();
 47
 148    if (SimManager.Instance.SimulatorConfig.EnableMissileTrailEffect) {
 049      InitializeMissileTrailParticlePool();
 050    }
 151    if (SimManager.Instance.SimulatorConfig.EnableExplosionEffect) {
 052      InitializeMissileExplosionParticlePool();
 053    }
 54
 55    // Subscribe to events.
 156    SimManager.Instance.OnNewInterceptor += RegisterNewInterceptor;
 157    SimManager.Instance.OnNewThreat += RegisterNewThreat;
 58
 159    SimManager.Instance.OnSimulationEnded += RegisterSimulationEnded;
 160  }
 61
 2962  private void Update() {
 2963    _missileTrailPoolCount = _missileTrailPool.Count;
 2964    _missileExplosionPoolCount = _missileExplosionPool.Count;
 2965  }
 66
 067  private void InitializeMissileTrailParticlePool() {
 68    // Grab from Resources/Prefabs/Effects.
 069    GameObject missileTrailPrefab =
 70        Resources.Load<GameObject>("Prefabs/Effects/InterceptorSmokeEffect");
 71
 72    // Pre-instantiate 10 missile trail particles.
 073    for (int i = 0; i < 10; ++i) {
 074      InstantiateMissileTrail(missileTrailPrefab);
 075    }
 76    // Instantiate over an interval.
 077    StartCoroutine(InstantiateMissileTrailsOverTime(missileTrailPrefab, 200, 0.05f));
 078  }
 79
 080  private GameObject InstantiateMissileTrail(GameObject prefab) {
 081    GameObject trail = Instantiate(prefab, transform);
 082    trail.GetComponent<ParticleSystem>().Stop();
 083    _missileTrailPool.Enqueue(trail);
 084    return trail;
 085  }
 86
 87  private IEnumerator InstantiateMissileTrailsOverTime(GameObject prefab, int count,
 088                                                       float duration) {
 089    float interval = duration / count;
 090    for (int i = 0; i < count; ++i) {
 091      InstantiateMissileTrail(prefab);
 092      yield return new WaitForSeconds(interval);
 093    }
 094  }
 95
 096  private void InitializeMissileExplosionParticlePool() {
 097    GameObject missileExplosionPrefab =
 98        Resources.Load<GameObject>("Prefabs/Effects/InterceptExplosionEffect");
 99    // Pre-instantiate 10 missile trail particles.
 0100    for (int i = 0; i < 10; ++i) {
 0101      InstantiateMissileExplosion(missileExplosionPrefab);
 0102    }
 0103    StartCoroutine(InstantiateMissileExplosionsOverTime(missileExplosionPrefab, 200, 0.05f));
 0104  }
 105
 0106  private GameObject InstantiateMissileExplosion(GameObject prefab) {
 0107    GameObject explosion = Instantiate(prefab, transform);
 0108    explosion.GetComponent<ParticleSystem>().Stop();
 0109    _missileExplosionPool.Enqueue(explosion);
 0110    return explosion;
 0111  }
 112
 113  private IEnumerator InstantiateMissileExplosionsOverTime(GameObject prefab, int count,
 0114                                                           float duration) {
 0115    float interval = duration / count;
 0116    for (int i = 0; i < count; ++i) {
 0117      InstantiateMissileExplosion(prefab);
 0118      yield return new WaitForSeconds(interval);
 0119    }
 0120  }
 121
 26122  private void RegisterNewInterceptor(IInterceptor interceptor) {
 26123    interceptor.OnHit += RegisterInterceptorHit;
 26124    interceptor.OnMiss += RegisterInterceptorMiss;
 26125    interceptor.OnTerminated += RegisterAgentTerminated;
 26126  }
 127
 0128  private void RegisterInterceptorHit(IInterceptor interceptor) {
 0129    if (SimManager.Instance.SimulatorConfig.EnableExplosionEffect) {
 0130      PlayMissileExplosion(interceptor.Position);
 0131    }
 0132    GameObject hitMarkerObject = SpawnHitMarker(interceptor.Position);
 0133    hitMarkerObject.GetComponent<UIEventMarker>().SetEventHit();
 0134  }
 135
 0136  private void RegisterInterceptorMiss(IInterceptor interceptor) {
 0137    GameObject hitMarkerObject = SpawnHitMarker(interceptor.Position);
 0138    hitMarkerObject.GetComponent<UIEventMarker>().SetEventMiss();
 0139  }
 140
 955141  private void RegisterNewThreat(IThreat threat) {
 955142    threat.OnTerminated += RegisterAgentTerminated;
 955143  }
 144
 0145  private void RegisterAgentTerminated(IAgent agent) {
 0146    if (SimManager.Instance.SimulatorConfig.PersistentFlightTrails) {
 0147      CommandeerAgentTrailRenderer(agent);
 0148    }
 0149  }
 150
 11151  private void RegisterSimulationEnded() {
 33152    foreach (var trailRenderer in _agentTrailRenderers) {
 0153      Destroy(trailRenderer.gameObject);
 0154    }
 11155    _agentTrailRenderers.Clear();
 11156  }
 157
 0158  private GameObject SpawnHitMarker(in Vector3 position) {
 0159    GameObject hitMarker =
 160        Instantiate(Resources.Load<GameObject>("Prefabs/HitMarker"), position, Quaternion.identity);
 0161    _hitMarkerList.Add(hitMarker);
 0162    return hitMarker;
 0163  }
 164
 0165  private GameObject PlayMissileExplosion(in Vector3 position) {
 0166    if (_missileExplosionPool.Count > 0) {
 0167      GameObject explosion = _missileExplosionPool.Dequeue();
 0168      explosion.transform.position = position;
 169
 0170      ParticleSystem particleSystem = explosion.GetComponent<ParticleSystem>();
 0171      if (particleSystem != null) {
 0172        particleSystem.Clear();
 0173        particleSystem.Play();
 0174        StartCoroutine(ReturnExplosionAfterDelay(explosion, particleSystem.main.duration));
 0175      } else {
 0176        Debug.LogError("Missile explosion particle has no ParticleSystem component.");
 0177        _missileExplosionPool.Enqueue(explosion);
 0178        return null;
 179      }
 180
 0181      return explosion;
 182    }
 0183    return null;
 0184  }
 185
 0186  private IEnumerator ReturnExplosionAfterDelay(GameObject explosion, float delay) {
 0187    yield return new WaitForSeconds(delay);
 0188    ReturnMissileExplosionParticle(explosion);
 0189  }
 190
 0191  private void ReturnMissileExplosionParticle(GameObject explosion) {
 0192    if (explosion == null) {
 0193      Debug.LogError("Attempted to return a null missile explosion particle.");
 0194      return;
 195    }
 196
 0197    explosion.transform.parent = transform;
 0198    explosion.transform.localPosition = Vector3.zero;
 0199    ParticleSystem particleSystem = explosion.GetComponent<ParticleSystem>();
 0200    if (particleSystem != null) {
 0201      particleSystem.Stop();
 0202      particleSystem.Clear();
 0203    } else {
 0204      Debug.LogError("Attempted to return a missile explosion particle with no particle system.");
 0205    }
 206
 0207    _missileExplosionPool.Enqueue(explosion);
 0208  }
 209
 0210  private void CommandeerAgentTrailRenderer(IAgent agent) {
 211    // Take the TrailRenderer component off of the agent, so it can be destroyed at the end of the
 212    // simulation.
 0213    TrailRenderer trailRenderer = agent.gameObject.GetComponentInChildren<TrailRenderer>();
 0214    if (trailRenderer != null) {
 0215      trailRenderer.transform.parent = transform;
 0216      _agentTrailRenderers.Add(trailRenderer);
 0217      trailRenderer.material = (agent is IThreat) ? ThreatTrailMatFaded : InterceptorTrailMatFaded;
 0218    } else {
 0219      Debug.LogWarning("Agent has no TrailRenderer component.");
 0220    }
 0221  }
 222}