< Summary

Class:Interceptor
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Interceptor.cs
Covered lines:72
Uncovered lines:83
Coverable lines:155
Total lines:238
Line coverage:46.4% (72 of 155)
Covered branches:0
Total branches:0
Covered methods:9
Total methods:17
Method coverage:52.9% (9 of 17)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Interceptor()0%110100%
Awake()0%110100%
IsAssignable()0%2100%
UpdateReady(...)0%2100%
FixedUpdate()0%220100%
UpdateBoost(...)0%220100%
UpdateMidCourse(...)0%2100%
CalcualteAccelerationInput(...)0%3.163073.68%
UpdateTargetModel(...)0%220100%
OnTriggerEnter(...)0%30500%
TerminateAgent()0%2100%
OnDestroy()0%20400%
AttachMissileTrailEffect()0%8.744033.33%
ReturnParticleToManager()0%20400%
UpdateMissileTrailEffect()0%64050%
DetatchMissileTrail()0%20400%
DrawDebugVectors()0%330100%

File(s)

/github/workspace/Assets/Scripts/Interceptor.cs

#LineLine coverage
 1using System.Collections;
 2using System.Collections.Generic;
 3using UnityEngine;
 4
 5public class Interceptor : Agent {
 6  [SerializeField]
 27  private float _navigationGain = 3f;  // Typically 3-5
 8
 9  [SerializeField]
 210  protected bool _showDebugVectors = true;
 11
 12  private GameObject _missileTrailEffect;
 213  private bool _missileTrailEffectAttached = false;
 14
 15  private Coroutine _returnParticleToManagerCoroutine;
 16
 17  private Vector3 _accelerationInput;
 18
 219  private double _elapsedTime = 0;
 20
 121  protected override void Awake() {
 122    base.Awake();
 123    SetFlightPhase(FlightPhase.INITIALIZED);
 124  }
 25
 26  // Return whether a target can be assigned to the interceptor.
 027  public override bool IsAssignable() {
 028    bool assignable = !HasAssignedTarget();
 029    return assignable;
 030  }
 31
 032  protected override void UpdateReady(double deltaTime) {
 033    Vector3 accelerationInput = Vector3.zero;
 034    Vector3 acceleration = CalculateAcceleration(accelerationInput);
 035    GetComponent<Rigidbody>().AddForce(acceleration, ForceMode.Acceleration);
 036  }
 37
 5138  protected override void FixedUpdate() {
 5139    base.FixedUpdate();
 10040    if (_showDebugVectors) {
 5041      DrawDebugVectors();
 5042    }
 5043  }
 44
 5145  protected override void UpdateBoost(double deltaTime) {
 10246    if (_missileTrailEffect == null) {
 5147      AttachMissileTrailEffect();
 5148    }
 5149    UpdateMissileTrailEffect();
 50
 51    // Calculate boost acceleration
 5152    float boostAcceleration =
 53        (float)(staticAgentConfig.boostConfig.boostAcceleration * Constants.kGravity);
 5154    Vector3 boostAccelerationVector = boostAcceleration * transform.forward;
 55
 56    // Add PN acceleration to boost acceleration
 5157    Vector3 controllerAcceleration = CalcualteAccelerationInput(deltaTime);
 5058    Vector3 accelerationInput = boostAccelerationVector + controllerAcceleration;
 59
 60    // Calculate the total acceleration
 5061    Vector3 acceleration = CalculateAcceleration(accelerationInput);
 62
 63    // Apply the acceleration force
 5064    GetComponent<Rigidbody>().AddForce(acceleration, ForceMode.Acceleration);
 5065  }
 66
 067  protected override void UpdateMidCourse(double deltaTime) {
 068    UpdateMissileTrailEffect();
 69
 070    _elapsedTime += deltaTime;
 071    Vector3 accelerationInput = CalcualteAccelerationInput(deltaTime);
 72
 73    // Calculate and set the total acceleration
 074    Vector3 acceleration = CalculateAcceleration(accelerationInput);
 075    GetComponent<Rigidbody>().AddForce(acceleration, ForceMode.Acceleration);
 076  }
 77
 5178  private Vector3 CalcualteAccelerationInput(double deltaTime) {
 5179    if (!HasAssignedTarget()) {
 080      return Vector3.zero;
 81    }
 82
 5183    UpdateTargetModel(deltaTime);
 84
 85    // Check whether the threat should be considered a miss
 5186    SensorOutput sensorOutput = GetComponent<Sensor>().Sense(_target);
 87    // DL: This causes trouble with Fateh110B (high-speed threats)
 88    // if (sensorOutput.velocity.range > 1000f) {
 89    //   this.HandleInterceptMiss();
 90    //   return Vector3.zero;
 91    // }
 92
 93    IController controller;
 5094    if (dynamicAgentConfig.dynamic_config.flight_config.augmentedPnEnabled) {
 095      controller = new ApnController(this, _navigationGain);
 5096    } else {
 5097      controller = new PnController(this, _navigationGain);
 5098    }
 5099    Vector3 accelerationInput = controller.Plan();
 100
 101    // Clamp the normal acceleration input to the maximum normal acceleration
 50102    float maxNormalAcceleration = CalculateMaxNormalAcceleration();
 50103    accelerationInput = Vector3.ClampMagnitude(accelerationInput, maxNormalAcceleration);
 50104    _accelerationInput = accelerationInput;
 50105    return accelerationInput;
 50106  }
 107
 51108  private void UpdateTargetModel(double deltaTime) {
 51109    _elapsedTime += deltaTime;
 51110    float sensorUpdatePeriod = 1f / dynamicAgentConfig.dynamic_config.sensor_config.frequency;
 61111    if (_elapsedTime >= sensorUpdatePeriod) {
 112      // TODO: Implement guidance filter to estimate state from sensor output
 113      // For now, we'll use the threat's actual state
 10114      _targetModel.SetPosition(_target.GetPosition());
 10115      _targetModel.SetVelocity(_target.GetVelocity());
 10116      _targetModel.SetAcceleration(_target.GetAcceleration());
 10117      _elapsedTime = 0;
 10118    }
 51119  }
 120
 0121  private void OnTriggerEnter(Collider other) {
 0122    if (other.gameObject.name == "Floor") {
 0123      this.HandleInterceptMiss();
 0124    }
 125    // Check if the collision is with another Agent
 0126    Agent otherAgent = other.gameObject.GetComponentInParent<Agent>();
 0127    if (otherAgent != null && otherAgent.GetComponent<Threat>() != null) {
 128      // Check kill probability before marking as hit
 0129      float killProbability = otherAgent.staticAgentConfig.hitConfig.killProbability;
 0130      GameObject markerObject = Instantiate(Resources.Load<GameObject>("Prefabs/HitMarkerPrefab"),
 131                                            transform.position, Quaternion.identity);
 0132      if (Random.value <= killProbability) {
 0133        markerObject.GetComponent<UIHitMarker>().SetHit();
 134        // Mark both this agent and the other agent as hit
 0135        this.HandleInterceptHit(otherAgent);
 0136        otherAgent.HandleInterceptHit(otherAgent);
 137
 0138      } else {
 0139        markerObject.GetComponent<UIHitMarker>().SetMiss();
 0140        this.HandleInterceptMiss();
 141        // otherAgent.MarkAsMiss();
 0142      }
 0143    }
 0144  }
 145
 0146  public override void TerminateAgent() {
 0147    DetatchMissileTrail();
 0148    base.TerminateAgent();
 0149  }
 150
 0151  public void OnDestroy() {
 0152    if (_returnParticleToManagerCoroutine != null) {
 0153      StopCoroutine(_returnParticleToManagerCoroutine);
 0154    }
 0155    if (_missileTrailEffect != null && ParticleManager.Instance != null) {
 0156      ParticleManager.Instance.ReturnMissileTrailParticle(_missileTrailEffect);
 0157      _missileTrailEffect = null;
 0158    }
 0159  }
 160
 51161  private void AttachMissileTrailEffect() {
 102162    if (_missileTrailEffect == null) {
 51163      _missileTrailEffect = ParticleManager.Instance.RequestMissileTrailParticle();
 51164      if (_missileTrailEffect != null) {
 0165        _missileTrailEffect.transform.parent = transform;
 0166        _missileTrailEffect.transform.localPosition = Vector3.zero;
 0167        _missileTrailEffectAttached = true;
 0168        ParticleSystem particleSystem = _missileTrailEffect.GetComponent<ParticleSystem>();
 0169        float duration = particleSystem.main.duration;
 170
 171        // Extend the duration of the missile trail effect to be the same as the boost time
 0172        if (duration < staticAgentConfig.boostConfig.boostTime) {
 0173          ParticleSystem.MainModule mainModule = particleSystem.main;
 0174          mainModule.duration = staticAgentConfig.boostConfig.boostTime;
 0175        }
 176
 0177        _returnParticleToManagerCoroutine = StartCoroutine(ReturnParticleToManager(duration * 2f));
 0178        particleSystem.Play();
 0179      }
 51180    }
 51181  }
 182
 0183  private IEnumerator ReturnParticleToManager(float delay) {
 0184    yield return new WaitForSeconds(delay);
 0185    if (_missileTrailEffect != null) {
 0186      ParticleManager.Instance.ReturnMissileTrailParticle(_missileTrailEffect);
 0187      _missileTrailEffect = null;
 0188      _missileTrailEffectAttached = false;
 0189    }
 0190  }
 191
 51192  private void UpdateMissileTrailEffect() {
 102193    if (_missileTrailEffect == null || !_missileTrailEffectAttached) {
 51194      return;
 195    }
 196
 197    // Get the particle effect duration time
 0198    float duration = _missileTrailEffect.GetComponent<ParticleSystem>().main.duration;
 0199    if (_timeSinceBoost > duration) {
 0200      DetatchMissileTrail();
 0201    }
 51202  }
 203
 0204  private void DetatchMissileTrail() {
 0205    if (_missileTrailEffect != null && _missileTrailEffectAttached) {
 0206      Vector3 currentPosition = _missileTrailEffect.transform.position;
 0207      _missileTrailEffect.transform.SetParent(null);
 0208      _missileTrailEffect.transform.position = currentPosition;
 0209      _missileTrailEffectAttached = false;
 210      // Stop emitting particles
 0211      ParticleSystem particleSystem = _missileTrailEffect.GetComponent<ParticleSystem>();
 0212      particleSystem.Stop();
 0213    }
 0214  }
 215
 50216  protected virtual void DrawDebugVectors() {
 100217    if (_target != null) {
 218      // Line of sight
 50219      Debug.DrawLine(transform.position, _target.transform.position, new Color(1, 1, 1, 0.15f));
 220
 221      // Velocity vector
 50222      Debug.DrawRay(transform.position, GetVelocity() * 0.01f, new Color(0, 0, 1, 0.15f));
 223
 224      // Current forward direction
 50225      Debug.DrawRay(transform.position, transform.forward * 5f, Color.yellow);
 226
 227      // Pitch axis (right)
 50228      Debug.DrawRay(transform.position, transform.right * 5f, Color.red);
 229
 230      // Yaw axis (up)
 50231      Debug.DrawRay(transform.position, transform.up * 5f, Color.magenta);
 232
 100233      if (_accelerationInput != null) {
 50234        Debug.DrawRay(transform.position, _accelerationInput * 1f, Color.green);
 50235      }
 50236    }
 50237  }
 238}