< Summary

Class:Interceptor
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Interceptor.cs
Covered lines:8
Uncovered lines:147
Coverable lines:155
Total lines:238
Line coverage:5.1% (8 of 155)
Covered branches:0
Total branches:0
Covered methods:2
Total methods:17
Method coverage:11.7% (2 of 17)

Metrics

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

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]
 67  private float _navigationGain = 3f;  // Typically 3-5
 8
 9  [SerializeField]
 610  protected bool _showDebugVectors = true;
 11
 12  private GameObject _missileTrailEffect;
 613  private bool _missileTrailEffectAttached = false;
 14
 15  private Coroutine _returnParticleToManagerCoroutine;
 16
 17  private Vector3 _accelerationInput;
 18
 619  private double _elapsedTime = 0;
 20
 021  protected override void Awake() {
 022    base.Awake();
 023    SetFlightPhase(FlightPhase.INITIALIZED);
 024  }
 25
 26  // Return whether a target can be assigned to the interceptor.
 627  public override bool IsAssignable() {
 628    bool assignable = !HasAssignedTarget();
 629    return assignable;
 630  }
 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
 038  protected override void FixedUpdate() {
 039    base.FixedUpdate();
 040    if (_showDebugVectors) {
 041      DrawDebugVectors();
 042    }
 043  }
 44
 045  protected override void UpdateBoost(double deltaTime) {
 046    if (_missileTrailEffect == null) {
 047      AttachMissileTrailEffect();
 048    }
 049    UpdateMissileTrailEffect();
 50
 51    // Calculate boost acceleration
 052    float boostAcceleration =
 53        (float)(staticAgentConfig.boostConfig.boostAcceleration * Constants.kGravity);
 054    Vector3 boostAccelerationVector = boostAcceleration * transform.forward;
 55
 56    // Add PN acceleration to boost acceleration
 057    Vector3 controllerAcceleration = CalcualteAccelerationInput(deltaTime);
 058    Vector3 accelerationInput = boostAccelerationVector + controllerAcceleration;
 59
 60    // Calculate the total acceleration
 061    Vector3 acceleration = CalculateAcceleration(accelerationInput);
 62
 63    // Apply the acceleration force
 064    GetComponent<Rigidbody>().AddForce(acceleration, ForceMode.Acceleration);
 065  }
 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
 078  private Vector3 CalcualteAccelerationInput(double deltaTime) {
 079    if (!HasAssignedTarget()) {
 080      return Vector3.zero;
 81    }
 82
 083    UpdateTargetModel(deltaTime);
 84
 85    // Check whether the threat should be considered a miss
 086    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;
 094    if (dynamicAgentConfig.dynamic_config.flight_config.augmentedPnEnabled) {
 095      controller = new ApnController(this, _navigationGain);
 096    } else {
 097      controller = new PnController(this, _navigationGain);
 098    }
 099    Vector3 accelerationInput = controller.Plan();
 100
 101    // Clamp the normal acceleration input to the maximum normal acceleration
 0102    float maxNormalAcceleration = CalculateMaxNormalAcceleration();
 0103    accelerationInput = Vector3.ClampMagnitude(accelerationInput, maxNormalAcceleration);
 0104    _accelerationInput = accelerationInput;
 0105    return accelerationInput;
 0106  }
 107
 0108  private void UpdateTargetModel(double deltaTime) {
 0109    _elapsedTime += deltaTime;
 0110    float sensorUpdatePeriod = 1f / dynamicAgentConfig.dynamic_config.sensor_config.frequency;
 0111    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
 0114      _targetModel.SetPosition(_target.GetPosition());
 0115      _targetModel.SetVelocity(_target.GetVelocity());
 0116      _targetModel.SetAcceleration(_target.GetAcceleration());
 0117      _elapsedTime = 0;
 0118    }
 0119  }
 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
 0161  private void AttachMissileTrailEffect() {
 0162    if (_missileTrailEffect == null) {
 0163      _missileTrailEffect = ParticleManager.Instance.RequestMissileTrailParticle();
 0164      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      }
 0180    }
 0181  }
 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
 0192  private void UpdateMissileTrailEffect() {
 0193    if (_missileTrailEffect == null || !_missileTrailEffectAttached) {
 0194      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    }
 0202  }
 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
 0216  protected virtual void DrawDebugVectors() {
 0217    if (_target != null) {
 218      // Line of sight
 0219      Debug.DrawLine(transform.position, _target.transform.position, new Color(1, 1, 1, 0.15f));
 220
 221      // Velocity vector
 0222      Debug.DrawRay(transform.position, GetVelocity() * 0.01f, new Color(0, 0, 1, 0.15f));
 223
 224      // Current forward direction
 0225      Debug.DrawRay(transform.position, transform.forward * 5f, Color.yellow);
 226
 227      // Pitch axis (right)
 0228      Debug.DrawRay(transform.position, transform.right * 5f, Color.red);
 229
 230      // Yaw axis (up)
 0231      Debug.DrawRay(transform.position, transform.up * 5f, Color.magenta);
 232
 0233      if (_accelerationInput != null) {
 0234        Debug.DrawRay(transform.position, _accelerationInput * 1f, Color.green);
 0235      }
 0236    }
 0237  }
 238}