< Summary

Class:Threat
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Threats/Threat.cs
Covered lines:50
Uncovered lines:53
Coverable lines:103
Total lines:181
Line coverage:48.5% (50 of 103)
Covered branches:0
Total branches:0
Covered methods:9
Total methods:11
Method coverage:81.8% (9 of 11)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Awake()0%110100%
SetAttackBehavior(...)0%110100%
LookupPowerTable(...)0%4.064084.62%
IsAssignable()0%2100%
Start()0%110100%
FixedUpdate()0%110100%
CalculateForwardAcceleration()0%2.022082.35%
GetClosestInterceptor()0%16.985021.74%
ShouldEvade()0%5.164058.33%
EvadeInterceptor(...)0%42600%
OnTriggerEnter(...)0%9.065045.45%

File(s)

/github/workspace/Assets/Scripts/Threats/Threat.cs

#LineLine coverage
 1using System.Collections;
 2using System.Collections.Generic;
 3using UnityEngine;
 4
 5public abstract class Threat : Agent {
 6  protected AttackBehavior _attackBehavior;
 7  [SerializeField]
 8  protected Vector3 _currentWaypoint;
 9  [SerializeField]
 10  protected Configs.Power _currentPower;
 11
 12  protected SensorOutput _sensorOutput;
 13  protected Sensor _sensor;
 14
 75515  protected override void Awake() {
 75516    base.Awake();
 75517    SetFlightPhase(FlightPhase.INITIALIZED);
 75518  }
 19
 75520  public void SetAttackBehavior(AttackBehavior attackBehavior) {
 75521    _attackBehavior = attackBehavior;
 22    // TODO(titan): Set the threat's initial target properly.
 75523    _target = SimManager.Instance.CreateDummyAgent(Vector3.zero, Vector3.zero);
 75524  }
 25
 521926  protected float LookupPowerTable(Configs.Power power) {
 7306627    foreach (var entry in staticConfig.PowerTable) {
 2609528      if (entry.Power == power) {
 521929        return entry.Speed;
 30      }
 1565731    }
 032    Debug.LogError($"Invalid power setting: {power}.");
 033    return 0f;
 521934  }
 35
 036  public override bool IsAssignable() {
 037    return false;
 038  }
 39
 75540  protected override void Start() {
 75541    base.Start();
 75542    _sensor = GetComponent<Sensor>();
 75543  }
 44
 597445  protected override void FixedUpdate() {
 597446    base.FixedUpdate();
 597447  }
 48
 484849  protected Vector3 CalculateForwardAcceleration() {
 484850    Vector3 transformVelocity = GetVelocity();
 51
 52    // Get the target speed for the current power setting.
 484853    float targetSpeed = LookupPowerTable(_currentPower);
 54
 55    // Calculate the current speed.
 484856    float currentSpeed = transformVelocity.magnitude;
 57
 58    // Speed error.
 484859    float speedError = targetSpeed - currentSpeed;
 60
 61    // Proportional gain for speed control.
 484862    float speedControlGain = 10.0f;  // Adjust this gain as necessary.
 63
 64    // Desired acceleration to adjust speed.
 484865    float desiredAccelerationMagnitude = speedControlGain * speedError;
 66
 67    // Limit the desired acceleration.
 484868    float maxForwardAcceleration = CalculateMaxForwardAcceleration();
 484869    desiredAccelerationMagnitude =
 70        Mathf.Clamp(desiredAccelerationMagnitude, -maxForwardAcceleration, maxForwardAcceleration);
 71
 72    // Acceleration direction (along current velocity direction).
 484873    Vector3 accelerationDirection = transformVelocity.normalized;
 74
 75    // Handle the zero velocity case.
 484876    if (accelerationDirection.magnitude < 0.1f) {
 077      accelerationDirection = transform.forward;  // Default direction.
 078    }
 79
 80    // Calculate the acceleration vector.
 484881    Vector3 speedAdjustmentAcceleration = accelerationDirection * desiredAccelerationMagnitude;
 484882    return speedAdjustmentAcceleration;
 484883  }
 84
 521985  protected Agent GetClosestInterceptor() {
 1043886    if (_interceptors.Count == 0) {
 521987      return null;
 88    }
 89
 090    Agent closestInterceptor = null;
 091    float minDistance = float.MaxValue;
 092    foreach (var interceptor in _interceptors) {
 093      if (!interceptor.IsTerminated()) {
 094        SensorOutput sensorOutput = _sensor.Sense(interceptor);
 095        if (sensorOutput.position.range < minDistance) {
 096          closestInterceptor = interceptor;
 097          minDistance = sensorOutput.position.range;
 098        }
 099      }
 0100    }
 0101    return closestInterceptor;
 5219102  }
 103
 5219104  protected bool ShouldEvade() {
 5219105    if (!agentConfig.DynamicConfig.FlightConfig.EvasionConfig.Enabled) {
 0106      return false;
 107    }
 108
 5219109    Agent closestInterceptor = GetClosestInterceptor();
 10438110    if (closestInterceptor == null) {
 5219111      return false;
 112    }
 113
 0114    float evasionRangeThreshold =
 115        agentConfig.DynamicConfig.FlightConfig.EvasionConfig.RangeThreshold;
 0116    SensorOutput sensorOutput = _sensor.Sense(closestInterceptor);
 0117    return sensorOutput.position.range <= evasionRangeThreshold && sensorOutput.velocity.range < 0;
 5219118  }
 119
 0120  protected Vector3 EvadeInterceptor(Agent interceptor) {
 0121    Vector3 transformVelocity = GetVelocity();
 0122    Vector3 interceptorVelocity = interceptor.GetVelocity();
 0123    Vector3 transformPosition = GetPosition();
 0124    Vector3 interceptorPosition = interceptor.GetPosition();
 125
 126    // Set power to maximum.
 0127    _currentPower = Configs.Power.Max;
 128
 129    // Evade the interceptor by changing the velocity to be normal to the interceptor's velocity.
 0130    Vector3 normalVelocity = Vector3.ProjectOnPlane(transformVelocity, interceptorVelocity);
 0131    Vector3 normalAccelerationDirection =
 132        Vector3.ProjectOnPlane(normalVelocity, transformVelocity).normalized;
 133
 134    // Turn away from the interceptor.
 0135    Vector3 relativePosition = interceptorPosition - transformPosition;
 0136    if (Vector3.Dot(relativePosition, normalAccelerationDirection) > 0) {
 0137      normalAccelerationDirection *= -1;
 0138    }
 139
 140    // Avoid evading straight down when near the ground.
 0141    float altitude = transformPosition.y;
 0142    float groundProximityThreshold =
 143        Mathf.Abs(transformVelocity.y) * 5f;  // Adjust threshold as necessary.
 0144    if (transformVelocity.y < 0 && altitude < groundProximityThreshold) {
 145      // Determine evasion direction based on angle to interceptor.
 0146      Vector3 toInterceptor = interceptorPosition - transformPosition;
 0147      Vector3 rightDirection = Vector3.Cross(Vector3.up, transform.forward);
 0148      float angle = Vector3.SignedAngle(transform.forward, toInterceptor, Vector3.up);
 149
 150      // Choose the direction that leads away from the interceptor.
 0151      Vector3 bestHorizontalDirection = angle > 0 ? -rightDirection : rightDirection;
 152
 153      // Blend between horizontal evasion and slight upward movement.
 0154      float blendFactor = 1 - (altitude / groundProximityThreshold);
 0155      normalAccelerationDirection =
 156          Vector3
 157              .Lerp(normalAccelerationDirection, bestHorizontalDirection + transform.up * 5f,
 158                    blendFactor)
 159              .normalized;
 0160    }
 0161    Vector3 normalAcceleration = normalAccelerationDirection * CalculateMaxNormalAcceleration();
 162
 163    // Adjust the forward speed.
 0164    Vector3 forwardAcceleration = CalculateForwardAcceleration();
 165
 0166    return normalAcceleration + forwardAcceleration;
 0167  }
 168
 29169  private void OnTriggerEnter(Collider other) {
 170    // Check if the threat hit the floor with a negative vertical speed.
 29171    if (other.gameObject.name == "Floor" && Vector3.Dot(GetVelocity(), Vector3.up) < 0) {
 0172      HandleHitGround();
 0173    }
 174
 175    // Check if the collision is with the asset.
 29176    DummyAgent otherAgent = other.gameObject.GetComponentInParent<DummyAgent>();
 29177    if (otherAgent != null && _target == otherAgent) {
 0178      HandleThreatHit();
 0179    }
 29180  }
 181}