159 lines
5.8 KiB
C#
159 lines
5.8 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class Missile : Agent {
|
|
[SerializeField]
|
|
protected bool _showDebugVectors = true;
|
|
|
|
[SerializeField]
|
|
private Vector3 _boostAcceleration;
|
|
// Return whether a target can be assigned to the missile.
|
|
public override bool IsAssignable() {
|
|
bool assignable = !HasLaunched() && !HasAssignedTarget();
|
|
return assignable;
|
|
}
|
|
|
|
// Assign the given target to the missile.
|
|
public override void AssignTarget(Agent target) {
|
|
base.AssignTarget(target);
|
|
}
|
|
|
|
// Unassign the target from the missile.
|
|
public override void UnassignTarget() {
|
|
base.UnassignTarget();
|
|
}
|
|
|
|
protected override void UpdateReady(double deltaTime) {
|
|
Vector3 accelerationInput = Vector3.zero;
|
|
Vector3 acceleration = CalculateAcceleration(accelerationInput);
|
|
// GetComponent<Rigidbody>().AddForce(acceleration, ForceMode.Acceleration);
|
|
}
|
|
|
|
protected override void FixedUpdate() {
|
|
base.FixedUpdate();
|
|
if (_showDebugVectors) {
|
|
DrawDebugVectors();
|
|
}
|
|
}
|
|
|
|
protected override void UpdateBoost(double deltaTime) {
|
|
// The missile 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<Rigidbody>().AddForce(acceleration, ForceMode.Acceleration);
|
|
_boostAcceleration = 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);
|
|
float dragAcceleration = -(airDrag + liftInducedDrag);
|
|
|
|
// Project the drag acceleration onto the forward direction
|
|
Vector3 dragAccelerationAlongRoll = dragAcceleration * transform.forward;
|
|
|
|
return accelerationInput + gravity + dragAccelerationAlongRoll;
|
|
}
|
|
|
|
private void OnTriggerEnter(Collider other) {
|
|
if (other.gameObject.name == "Floor") {
|
|
this.MarkAsMiss();
|
|
}
|
|
// Check if the collision is with another Agent
|
|
Agent otherAgent = other.gameObject.GetComponentInParent<Agent>();
|
|
if (otherAgent != null && otherAgent.GetComponent<Target>() != null) {
|
|
// Check kill probability before marking as hit
|
|
float killProbability = _staticConfig.hitConfig.killProbability;
|
|
GameObject markerObject = Instantiate(Resources.Load<GameObject>("Prefabs/HitMarkerPrefab"),
|
|
transform.position, Quaternion.identity);
|
|
if (Random.value <= killProbability) {
|
|
// Set green for hit
|
|
markerObject.GetComponent<Renderer>().material.color = new Color(0, 1, 0, 0.15f);
|
|
// Mark both this agent and the other agent as hit
|
|
this.MarkAsHit();
|
|
otherAgent.MarkAsHit();
|
|
|
|
} else {
|
|
// Set red for miss
|
|
markerObject.GetComponent<Renderer>().material.color = new Color(1, 0, 0, 0.15f);
|
|
this.MarkAsMiss();
|
|
// otherAgent.MarkAsMiss();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected float CalculateMaxAcceleration() {
|
|
float maxReferenceAcceleration =
|
|
(float)(_staticConfig.accelerationConfig.maxReferenceAcceleration * Constants.kGravity);
|
|
float referenceSpeed = _staticConfig.accelerationConfig.referenceSpeed;
|
|
return Mathf.Pow(GetComponent<Rigidbody>().velocity.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);
|
|
}
|
|
}
|
|
}
|