micromissiles-unity/Assets/Scripts/SimManager.cs

269 lines
8.5 KiB
C#
Raw Normal View History

2024-09-12 00:17:21 -07:00
using System.Collections;
using System.Collections.Generic;
2024-09-12 15:44:55 -07:00
using System.Linq;
2024-09-12 00:17:21 -07:00
using UnityEngine;
public class SimManager : MonoBehaviour
{
2024-09-12 15:44:55 -07:00
// Singleton instance
public static SimManager Instance { get; private set; }
2024-09-12 00:17:21 -07:00
[SerializeField]
public SimulationConfig simulationConfig;
2024-09-12 15:44:55 -07:00
private List<Missile> _missiles = new List<Missile>();
private List<Target> _unassignedTargets = new List<Target>();
private List<Target> _targets = new List<Target>();
2024-09-12 15:44:55 -07:00
private float _elapsedSimulationTime = 0f;
2024-09-12 00:17:21 -07:00
private float endTime = 100f; // Set an appropriate end time
private bool simulationRunning = false;
2024-09-12 15:44:55 -07:00
private IAssignment _assignmentScheme;
public double GetElapsedSimulationTime()
{
return _elapsedSimulationTime;
}
2024-09-12 00:17:21 -07:00
2024-09-12 15:44:55 -07:00
void Awake()
{
// Ensure only one instance of SimManager exists
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
2024-09-12 00:17:21 -07:00
void Start() {
// Slow down time by simulationConfig.timeScale
2024-09-12 15:44:55 -07:00
if(Instance == this) {
Time.timeScale = simulationConfig.timeScale;
Time.fixedDeltaTime = Time.timeScale * 0.02f;
Time.maximumDeltaTime = Time.timeScale * 0.15f;
InitializeSimulation();
simulationRunning = true;
}
2024-09-12 00:17:21 -07:00
}
private void InitializeSimulation()
2024-09-12 00:17:21 -07:00
{
2024-09-12 15:44:55 -07:00
List<Missile> missiles = new List<Missile>();
2024-09-12 00:17:21 -07:00
// Create missiles based on config
foreach (var swarmConfig in simulationConfig.missile_swarm_configs)
{
for (int i = 0; i < swarmConfig.num_agents; i++) {
var missile = CreateMissile(swarmConfig.agent_config);
}
}
2024-09-12 15:44:55 -07:00
List<Target> targets = new List<Target>();
2024-09-12 00:17:21 -07:00
// Create targets based on config
foreach (var swarmConfig in simulationConfig.target_swarm_configs)
{
for (int i = 0; i < swarmConfig.num_agents; i++) {
var target = CreateTarget(swarmConfig.agent_config);
2024-09-12 15:44:55 -07:00
2024-09-12 00:17:21 -07:00
}
}
2024-09-12 15:44:55 -07:00
_assignmentScheme = new ThreatAssignment();
2024-09-12 00:17:21 -07:00
// Perform initial assignment
}
2024-09-12 15:44:55 -07:00
public void AssignMissilesToTargets()
2024-09-12 00:17:21 -07:00
{
2024-09-12 15:44:55 -07:00
AssignMissilesToTargets(_missiles);
}
2024-09-12 00:17:21 -07:00
public void RegisterTargetMiss(Target target) {
_unassignedTargets.Add(target);
}
2024-09-12 15:44:55 -07:00
public void AssignMissilesToTargets(List<Missile> missilesToAssign)
{
// Convert Missile and Target lists to Agent lists
List<Agent> missileAgents = new List<Agent>(missilesToAssign.ConvertAll(m => m as Agent));
// Convert Target list to Agent list, excluding already assigned targets
List<Agent> targetAgents = _unassignedTargets.ToList<Agent>();
2024-09-12 00:17:21 -07:00
// Perform the assignment
2024-09-12 15:44:55 -07:00
IEnumerable<IAssignment.AssignmentItem> assignments = _assignmentScheme.Assign(missileAgents, targetAgents);
2024-09-12 00:17:21 -07:00
// Apply the assignments to the missiles
2024-09-12 15:44:55 -07:00
foreach (var assignment in assignments)
2024-09-12 00:17:21 -07:00
{
2024-09-12 15:44:55 -07:00
if (assignment.MissileIndex < missilesToAssign.Count)
{
Missile missile = missilesToAssign[assignment.MissileIndex];
Target target = _unassignedTargets[assignment.TargetIndex];
2024-09-12 15:44:55 -07:00
missile.AssignTarget(target);
Debug.Log($"Missile {missile.name} assigned to target {target.name}");
2024-09-12 15:44:55 -07:00
}
2024-09-12 00:17:21 -07:00
}
// TODO this whole function should be optimized
_unassignedTargets.RemoveAll(target => missilesToAssign.Any(missile => missile.GetAssignedTarget() == target));
2024-09-12 00:17:21 -07:00
}
2024-09-12 15:44:55 -07:00
public Missile CreateMissile(AgentConfig config)
2024-09-12 00:17:21 -07:00
{
2024-09-12 15:44:55 -07:00
string prefabName = config.missile_type switch
2024-09-12 00:17:21 -07:00
{
2024-09-12 15:44:55 -07:00
MissileType.HYDRA_70 => "Hydra70",
MissileType.MICROMISSILE => "Micromissile",
_ => "Hydra70"
};
2024-09-12 00:17:21 -07:00
2024-09-12 15:44:55 -07:00
GameObject missileObject = CreateAgent(config, prefabName);
if (missileObject == null) return null;
2024-09-12 00:17:21 -07:00
2024-09-12 15:44:55 -07:00
// Missile-specific logic
2024-09-12 00:17:21 -07:00
switch(config.dynamic_config.sensor_config.type) {
case SensorType.IDEAL:
missileObject.AddComponent<IdealSensor>();
break;
default:
Debug.LogError($"Sensor type '{config.dynamic_config.sensor_config.type}' not found.");
break;
}
2024-09-12 15:44:55 -07:00
// Missile missile = missileObject.GetComponent<Missile>();
// if (missile == null)
// {
// Debug.LogError($"Missile component not found on prefab '{prefabName}'.");
// Destroy(missileObject);
// return null;
// }
// missile.SetAgentConfig(config);
_missiles.Add(missileObject.GetComponent<Missile>());
// Assign a unique and simple target ID
int missileId = _missiles.Count;
missileObject.name = $"{config.missile_type}_Missile_{missileId}";
return missileObject.GetComponent<Missile>();
}
2024-09-12 00:17:21 -07:00
2024-09-12 15:44:55 -07:00
private Target CreateTarget(AgentConfig config)
{
string prefabName = config.target_type switch
2024-09-12 00:17:21 -07:00
{
2024-09-12 15:44:55 -07:00
TargetType.DRONE => "DroneTarget",
TargetType.MISSILE => "MissileTarget",
_ => throw new System.ArgumentException($"Unsupported target type: {config.target_type}")
};
GameObject targetObject = CreateAgent(config, prefabName);
if (targetObject == null) return null;
// Target target = targetObject.GetComponent<Target>();
// if (target == null)
// {
// Debug.LogError($"Target component not found on prefab '{config.prefabName}'.");
// Destroy(targetObject);
// return null;
// }
// target.SetAgentConfig(config);
_targets.Add(targetObject.GetComponent<Target>());
_unassignedTargets.Add(targetObject.GetComponent<Target>());
// Assign a unique and simple target ID
int targetId = _targets.Count;
targetObject.name = $"{config.target_type}_Target_{targetId}";
return targetObject.GetComponent<Target>();
2024-09-12 00:17:21 -07:00
}
2024-09-12 15:44:55 -07:00
public GameObject CreateAgent(AgentConfig config, string prefabName)
2024-09-12 00:17:21 -07:00
{
2024-09-12 15:44:55 -07:00
GameObject prefab = Resources.Load<GameObject>($"Prefabs/{prefabName}");
if (prefab == null)
2024-09-12 00:17:21 -07:00
{
2024-09-12 15:44:55 -07:00
Debug.LogError($"Prefab '{prefabName}' not found in Resources/Prefabs folder.");
2024-09-12 00:17:21 -07:00
return null;
}
Vector3 noiseOffset = Utilities.GenerateRandomNoise(config.standard_deviation.position);
Vector3 noisyPosition = config.initial_state.position + noiseOffset;
2024-09-12 15:44:55 -07:00
GameObject agentObject = Instantiate(prefab, noisyPosition, Quaternion.Euler(config.initial_state.rotation));
2024-09-12 00:17:21 -07:00
2024-09-12 15:44:55 -07:00
Rigidbody agentRigidbody = agentObject.GetComponent<Rigidbody>();
2024-09-12 00:17:21 -07:00
Vector3 velocityNoise = Utilities.GenerateRandomNoise(config.standard_deviation.velocity);
Vector3 noisyVelocity = config.initial_state.velocity + velocityNoise;
2024-09-12 15:44:55 -07:00
agentRigidbody.velocity = noisyVelocity;
2024-09-12 00:17:21 -07:00
2024-09-12 15:44:55 -07:00
agentObject.GetComponent<Agent>().SetAgentConfig(config);
2024-09-12 00:17:21 -07:00
2024-09-12 15:44:55 -07:00
return agentObject;
}
2024-09-12 00:17:21 -07:00
private void RestartSimulation()
{
// Reset simulation time
2024-09-12 15:44:55 -07:00
_elapsedSimulationTime = 0f;
2024-09-12 00:17:21 -07:00
simulationRunning = true;
// Clear existing missiles and targets
2024-09-12 15:44:55 -07:00
foreach (var missile in _missiles)
2024-09-12 00:17:21 -07:00
{
if (missile != null)
{
Destroy(missile.gameObject);
}
}
2024-09-12 15:44:55 -07:00
_missiles.Clear();
2024-09-12 00:17:21 -07:00
2024-09-12 15:44:55 -07:00
foreach (var target in _targets)
2024-09-12 00:17:21 -07:00
{
if (target != null)
{
Destroy(target.gameObject);
}
}
2024-09-12 15:44:55 -07:00
_targets.Clear();
2024-09-12 00:17:21 -07:00
InitializeSimulation();
}
void Update()
{
// Check if all missiles have terminated
bool allMissilesTerminated = true;
2024-09-12 15:44:55 -07:00
foreach (var missile in _missiles)
2024-09-12 00:17:21 -07:00
{
if (missile != null && !missile.IsHit() && !missile.IsMiss())
2024-09-12 00:17:21 -07:00
{
allMissilesTerminated = false;
break;
}
}
// If all missiles have terminated, restart the simulation
if (allMissilesTerminated)
{
RestartSimulation();
}
2024-09-12 15:44:55 -07:00
if (simulationRunning && _elapsedSimulationTime < endTime)
2024-09-12 00:17:21 -07:00
{
2024-09-12 15:44:55 -07:00
_elapsedSimulationTime += Time.deltaTime;
2024-09-12 00:17:21 -07:00
}
2024-09-12 15:44:55 -07:00
else if (_elapsedSimulationTime >= endTime)
2024-09-12 00:17:21 -07:00
{
simulationRunning = false;
Debug.Log("Simulation completed.");
}
}
}