using System.Collections; using System.Collections.Generic; using UnityEngine; public class Interceptor : Agent { [SerializeField] protected bool _showDebugVectors = true; // Return whether a target can be assigned to the interceptor. public override bool IsAssignable() { bool assignable = !HasLaunched() && !HasAssignedTarget(); return assignable; } // Assign the given target to the interceptor. public override void AssignTarget(Agent target) { base.AssignTarget(target); } // Unassign the target from the interceptor. public override void UnassignTarget() { base.UnassignTarget(); } protected override void UpdateReady(double deltaTime) { Vector3 accelerationInput = Vector3.zero; Vector3 acceleration = CalculateAcceleration(accelerationInput); // GetComponent().AddForce(acceleration, ForceMode.Acceleration); } protected override void FixedUpdate() { base.FixedUpdate(); if (_showDebugVectors) { DrawDebugVectors(); } } protected override void UpdateBoost(double deltaTime) { // The interceptor only accelerates along its roll axis (forward in Unity) Vector3 rollAxis = transform.forward; // Calculate boost acceleration float boostAcceleration = (float)(_staticConfig.boostConfig.boostAcceleration * Constants.kGravity); Vector3 accelerationInput = boostAcceleration * rollAxis; // Calculate the total acceleration Vector3 acceleration = CalculateAcceleration(accelerationInput); // Apply the acceleration force GetComponent().AddForce(acceleration, ForceMode.Acceleration); } protected override void UpdateMidCourse(double deltaTime) {} protected Vector3 CalculateAcceleration(Vector3 accelerationInput, bool compensateForGravity = false) { Vector3 gravity = Physics.gravity; if (compensateForGravity) { Vector3 gravityProjection = CalculateGravityProjectionOnPitchAndYaw(); accelerationInput -= gravityProjection; } float airDrag = CalculateDrag(); float liftInducedDrag = CalculateLiftInducedDrag(accelerationInput + gravity); float dragAcceleration = -(airDrag + liftInducedDrag); // Project the drag acceleration onto the forward direction Vector3 dragAccelerationAlongRoll = dragAcceleration * transform.forward; _dragAcceleration = dragAccelerationAlongRoll; return accelerationInput + gravity + dragAccelerationAlongRoll; } private void OnTriggerEnter(Collider other) { if (other.gameObject.name == "Floor") { this.HandleInterceptMiss(); } // Check if the collision is with another Agent Agent otherAgent = other.gameObject.GetComponentInParent(); if (otherAgent != null && otherAgent.GetComponent() != null) { // Check kill probability before marking as hit float killProbability = _staticConfig.hitConfig.killProbability; GameObject markerObject = Instantiate(Resources.Load("Prefabs/HitMarkerPrefab"), transform.position, Quaternion.identity); if (Random.value <= killProbability) { // Set green for hit markerObject.GetComponent().material.color = new Color(0, 1, 0, 0.15f); // Mark both this agent and the other agent as hit this.HandleInterceptHit(otherAgent); otherAgent.HandleInterceptHit(otherAgent); } else { // Set red for miss markerObject.GetComponent().material.color = new Color(1, 0, 0, 0.15f); this.HandleInterceptMiss(); // otherAgent.MarkAsMiss(); } } } protected float CalculateMaxAcceleration() { float maxReferenceAcceleration = (float)(_staticConfig.accelerationConfig.maxReferenceAcceleration * Constants.kGravity); float referenceSpeed = _staticConfig.accelerationConfig.referenceSpeed; return Mathf.Pow(GetComponent().linearVelocity.magnitude / referenceSpeed, 2) * maxReferenceAcceleration; } protected Vector3 CalculateGravityProjectionOnPitchAndYaw() { Vector3 gravity = Physics.gravity; Vector3 pitchAxis = transform.right; Vector3 yawAxis = transform.up; // Project the gravity onto the pitch and yaw axes float gravityProjectionPitchCoefficient = Vector3.Dot(gravity, pitchAxis); float gravityProjectionYawCoefficient = Vector3.Dot(gravity, yawAxis); // Return the sum of the projections return gravityProjectionPitchCoefficient * pitchAxis + gravityProjectionYawCoefficient * yawAxis; } private float CalculateDrag() { float dragCoefficient = _staticConfig.liftDragConfig.dragCoefficient; float crossSectionalArea = _staticConfig.bodyConfig.crossSectionalArea; float mass = _staticConfig.bodyConfig.mass; float dynamicPressure = (float)GetDynamicPressure(); float dragForce = dragCoefficient * dynamicPressure * crossSectionalArea; return dragForce / mass; } private float CalculateLiftInducedDrag(Vector3 accelerationInput) { float liftAcceleration = (accelerationInput - Vector3.Dot(accelerationInput, transform.up) * transform.up).magnitude; float liftDragRatio = _staticConfig.liftDragConfig.liftDragRatio; return Mathf.Abs(liftAcceleration / liftDragRatio); } protected virtual void DrawDebugVectors() { if (_target != null) { // Line of sight Debug.DrawLine(transform.position, _target.transform.position, new Color(1, 1, 1, 0.15f)); // Velocity vector Debug.DrawRay(transform.position, GetVelocity() * 0.01f, new Color(0, 0, 1, 0.15f)); // Current forward direction Debug.DrawRay(transform.position, transform.forward * 5f, Color.yellow); // Pitch axis (right) Debug.DrawRay(transform.position, transform.right * 5f, Color.red); // Yaw axis (up) Debug.DrawRay(transform.position, transform.up * 5f, Color.magenta); } } }