< Summary

Class:SimManager
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Managers/SimManager.cs
Covered lines:105
Uncovered lines:282
Coverable lines:387
Total lines:598
Line coverage:27.1% (105 of 387)
Covered branches:0
Total branches:0
Covered methods:9
Total methods:49
Method coverage:18.3% (9 of 49)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SimManager()0%2100%
SimManager()0%110100%
GetElapsedSimulationTime()0%2100%
GetCostLaunchedInterceptors()0%2100%
GetCostDestroyedThreats()0%2100%
GetActiveInterceptors()0%2100%
GetActiveThreats()0%6200%
GetActiveAgents()0%12300%
GenerateSwarmTitle(...)0%2100%
GenerateInterceptorSwarmTitle(...)0%2100%
GenerateSubmunitionsSwarmTitle(...)0%2100%
GenerateThreatSwarmTitle(...)0%2100%
Awake()0%6200%
Start()0%6200%
Update()0%2100%
SetTimeScale(...)0%2100%
StartSimulation()0%6200%
PauseSimulation()0%2100%
ResumeSimulation()0%2100%
IsSimulationPaused()0%2100%
InitializeSimulation()0%30500%
AddInterceptorSwarm(...)0%20400%
AddSubmunitionsSwarm(...)0%20400%
LookupSubmunitionSwarmIndexInInterceptorSwarm(...)0%6200%
AddThreatSwarm(...)0%20400%
GetAllAgentsCenter()0%12300%
GetSwarmCenter(...)0%30500%
GetInterceptorSwarms()0%2100%
GetSubmunitionsSwarms()0%2100%
GetThreatSwarms()0%2100%
DestroyInterceptorInSwarm(...)0%56700%
DestroySubmunitionInSwarm(...)0%12300%
DestroyThreatInSwarm(...)0%42600%
RegisterInterceptorHit(...)0%20400%
RegisterInterceptorMiss(...)0%20400%
RegisterThreatHit(...)0%2100%
RegisterThreatMiss(...)0%2100%
LoadAttackBehavior(...)0%2.062075%
CreateDummyAgent(...)0%330100%
CreateInterceptor(...)0%7.837074.29%
CreateThreat(...)0%6.356078.57%
CreateAgent(...)0%2.042078.57%
CreateRandomAgent(...)0%3.273068.75%
LoadNewConfig(...)0%6200%
RestartSimulation()0%1321100%
FixedUpdate()0%20400%
QuitSimulation()0%2100%

File(s)

/github/workspace/Assets/Scripts/Managers/SimManager.cs

#LineLine coverage
 1using System.Collections;
 2using System.Collections.Generic;
 3using System.Linq;
 4using UnityEngine;
 5
 6// Manages the simulation by handling missiles, targets, and their assignments.
 7// Implements the Singleton pattern to ensure only one instance exists.
 8public class SimManager : MonoBehaviour {
 9  // Map from the agent type to the prefab class name.
 10  // The prefab class must exist in the Resources/Prefabs directory.
 011  private static readonly Dictionary<Configs.AgentType, string> AgentTypePrefabMap = new() {
 12    { Configs.AgentType.CarrierInterceptor, "CarrierInterceptor" },
 13    { Configs.AgentType.MissileInterceptor, "MissileInterceptor" },
 14    { Configs.AgentType.FixedWingThreat, "FixedWingThreat" },
 15    { Configs.AgentType.RotaryWingThreat, "RotaryWingThreat" },
 16  };
 17
 18  // Singleton instance of SimManager.
 4819  public static SimManager Instance { get; set; }
 20
 21  // Simulation configuration.
 22  [SerializeField]
 23  public Configs.SimulationConfig SimulationConfig;
 24
 25  // Simulator configuration.
 26  public Configs.SimulatorConfig SimulatorConfig;
 27
 28  private const string _defaultConfig = "7_quadcopters.pbtxt";
 29
 1130  private List<Interceptor> _activeInterceptors = new List<Interceptor>();
 1131  private List<Interceptor> _interceptorObjects = new List<Interceptor>();
 1132  private List<Threat> _threatObjects = new List<Threat>();
 33
 1134  private List<GameObject> _dummyAgentObjects = new List<GameObject>();
 1135  private Dictionary<(Vector3, Vector3), GameObject> _dummyAgentTable =
 36      new Dictionary<(Vector3, Vector3), GameObject>();
 37
 38  // Inclusive of all, including submunitions swarms.
 39  // The boolean indicates whether the agent is active (true) or inactive (false).
 1140  private List<List<(Agent, bool)>> _interceptorSwarms = new List<List<(Agent, bool)>>();
 1141  private List<List<(Agent, bool)>> _submunitionsSwarms = new List<List<(Agent, bool)>>();
 1142  private List<List<(Agent, bool)>> _threatSwarms = new List<List<(Agent, bool)>>();
 43
 1144  private Dictionary<Agent, List<(Agent, bool)>> _interceptorSwarmMap =
 45      new Dictionary<Agent, List<(Agent, bool)>>();
 46
 1147  private Dictionary<Agent, List<(Agent, bool)>> _submunitionsSwarmMap =
 48      new Dictionary<Agent, List<(Agent, bool)>>();
 1149  private Dictionary<Agent, List<(Agent, bool)>> _threatSwarmMap =
 50      new Dictionary<Agent, List<(Agent, bool)>>();
 51
 52  // Maps a submunition swarm to its corresponding interceptor swarm.
 1153  private Dictionary<List<(Agent, bool)>, List<(Agent, bool)>> _submunitionInterceptorSwarmMap =
 54      new Dictionary<List<(Agent, bool)>, List<(Agent, bool)>>();
 55
 56  // Events to subscribe to for changes in each of the swarm tables.
 57  public delegate void SwarmEventHandler(List<List<(Agent, bool)>> swarm);
 58  public event SwarmEventHandler OnInterceptorSwarmChanged;
 59  public event SwarmEventHandler OnSubmunitionsSwarmChanged;
 60  public event SwarmEventHandler OnThreatSwarmChanged;
 61
 1162  private float _elapsedSimulationTime = 0f;
 1163  private bool _isSimulationPaused = false;
 64
 1165  private float _costLaunchedInterceptors = 0f;
 1166  private float _costDestroyedThreats = 0f;
 67
 68  public delegate void SimulationEventHandler();
 69  public event SimulationEventHandler OnSimulationEnded;
 70  public event SimulationEventHandler OnSimulationStarted;
 71
 72  public delegate void NewThreatEventHandler(Threat threat);
 73  public event NewThreatEventHandler OnNewThreat;
 74
 75  public delegate void NewInterceptorEventHandler(Interceptor interceptor);
 76  public event NewInterceptorEventHandler OnNewInterceptor;
 77
 78  // Returns the elapsed simulation time in seconds.
 079  public double GetElapsedSimulationTime() {
 080    return _elapsedSimulationTime;
 081  }
 82
 83  // Returns the total cost of launched interceptors.
 084  public double GetCostLaunchedInterceptors() {
 085    return _costLaunchedInterceptors;
 086  }
 87
 88  // Returns the total cost of destroyed threats.
 089  public double GetCostDestroyedThreats() {
 090    return _costDestroyedThreats;
 091  }
 92
 093  public List<Interceptor> GetActiveInterceptors() {
 094    return _activeInterceptors;
 095  }
 96
 097  public List<Threat> GetActiveThreats() {
 098    return _threatObjects.Where(threat => !threat.IsTerminated()).ToList();
 099  }
 100
 0101  public List<Agent> GetActiveAgents() {
 0102    return _activeInterceptors.ConvertAll(interceptor => interceptor as Agent)
 0103        .Concat(GetActiveThreats().ConvertAll(threat => threat as Agent))
 104        .ToList();
 0105  }
 106
 0107  public string GenerateSwarmTitle(List<(Agent, bool)> swarm, int index) {
 0108    string swarmTitle = swarm[0].Item1.name;
 0109    swarmTitle = swarmTitle.Split('_')[0];
 0110    swarmTitle += $"_{index}";
 0111    return swarmTitle;
 0112  }
 113
 0114  public string GenerateInterceptorSwarmTitle(List<(Agent, bool)> swarm) {
 0115    return GenerateSwarmTitle(swarm, _interceptorSwarms.IndexOf(swarm));
 0116  }
 117
 0118  public string GenerateSubmunitionsSwarmTitle(List<(Agent, bool)> swarm) {
 0119    return GenerateSwarmTitle(swarm, LookupSubmunitionSwarmIndexInInterceptorSwarm(swarm));
 0120  }
 121
 0122  public string GenerateThreatSwarmTitle(List<(Agent, bool)> swarm) {
 0123    return GenerateSwarmTitle(swarm, _threatSwarms.IndexOf(swarm));
 0124  }
 125
 0126  void Awake() {
 127    // Ensure that only one instance of SimManager exists.
 0128    if (Instance == null) {
 0129      Instance = this;
 0130      DontDestroyOnLoad(gameObject);
 0131    } else {
 0132      Destroy(gameObject);
 0133    }
 0134    SimulationConfig = ConfigLoader.LoadSimulationConfig(_defaultConfig);
 0135    SimulatorConfig = ConfigLoader.LoadSimulatorConfig();
 0136  }
 137
 0138  void Start() {
 0139    if (Instance == this) {
 0140      _isSimulationPaused = false;
 0141      StartSimulation();
 0142      ResumeSimulation();
 0143    }
 0144  }
 145
 0146  void Update() {}
 147
 0148  public void SetTimeScale(float timeScale) {
 0149    Time.timeScale = timeScale;
 150    // Time.fixedDeltaTime is derived from the simulator configuration.
 0151    Time.maximumDeltaTime = Time.fixedDeltaTime * 3;
 0152  }
 153
 0154  public void StartSimulation() {
 0155    InitializeSimulation();
 156
 157    // Invoke the simulation started event to let listeners know to invoke their own handler
 158    // behavior.
 0159    UIManager.Instance.LogActionMessage("[SIM] Simulation started.");
 0160    OnSimulationStarted?.Invoke();
 0161  }
 162
 0163  public void PauseSimulation() {
 0164    SetTimeScale(0);
 0165    Time.fixedDeltaTime = 0;
 0166    _isSimulationPaused = true;
 0167  }
 168
 0169  public void ResumeSimulation() {
 0170    Time.fixedDeltaTime = (float)(1.0f / SimulatorConfig.PhysicsUpdateRate);
 0171    SetTimeScale(SimulationConfig.TimeScale);
 0172    _isSimulationPaused = false;
 0173  }
 174
 0175  public bool IsSimulationPaused() {
 0176    return _isSimulationPaused;
 0177  }
 178
 0179  private void InitializeSimulation() {
 0180    if (!IsSimulationPaused()) {
 181      // If the simulation was not paused, we need to update the time scale.
 0182      SetTimeScale(SimulationConfig.TimeScale);
 0183      Time.fixedDeltaTime = (float)(1.0f / SimulatorConfig.PhysicsUpdateRate);
 184      // If the simulation was paused, then ResumeSimulation will handle updating the time scale and
 185      // fixed delta time from the newly loaded configuration.
 0186    }
 187
 188    // Create threats based on the configuration.
 0189    List<Agent> targets = new List<Agent>();
 0190    foreach (var swarmConfig in SimulationConfig.ThreatSwarmConfigs) {
 0191      List<Agent> swarm = new List<Agent>();
 0192      for (int i = 0; i < swarmConfig.NumAgents; ++i) {
 0193        Threat threat = CreateThreat(swarmConfig.AgentConfig);
 0194        swarm.Add(threat);
 0195      }
 0196      AddThreatSwarm(swarm);
 0197    }
 0198  }
 199
 0200  public void AddInterceptorSwarm(List<Agent> swarm) {
 0201    List<(Agent, bool)> swarmTuple = swarm.ConvertAll(agent => (agent, true));
 0202    _interceptorSwarms.Add(swarmTuple);
 0203    foreach (var interceptor in swarm) {
 0204      _interceptorSwarmMap[interceptor] = swarmTuple;
 0205    }
 0206    OnInterceptorSwarmChanged?.Invoke(_interceptorSwarms);
 0207  }
 208
 0209  public void AddSubmunitionsSwarm(List<Agent> swarm) {
 0210    List<(Agent, bool)> swarmTuple = swarm.ConvertAll(agent => (agent, true));
 0211    _submunitionsSwarms.Add(swarmTuple);
 0212    foreach (var submunition in swarm) {
 0213      _submunitionsSwarmMap[submunition] = swarmTuple;
 0214    }
 0215    AddInterceptorSwarm(swarm);
 0216    _submunitionInterceptorSwarmMap[swarmTuple] = _interceptorSwarms[_interceptorSwarms.Count - 1];
 0217    OnSubmunitionsSwarmChanged?.Invoke(_submunitionsSwarms);
 0218  }
 219
 0220  public int LookupSubmunitionSwarmIndexInInterceptorSwarm(List<(Agent, bool)> swarm) {
 0221    if (_submunitionInterceptorSwarmMap.TryGetValue(swarm, out var interceptorSwarm)) {
 0222      return _interceptorSwarms.IndexOf(interceptorSwarm);
 223    }
 224    // Return -1 if the swarm is not found.
 0225    return -1;
 0226  }
 227
 0228  public void AddThreatSwarm(List<Agent> swarm) {
 0229    List<(Agent, bool)> swarmTuple = swarm.ConvertAll(agent => (agent, true));
 0230    _threatSwarms.Add(swarmTuple);
 0231    foreach (var threat in swarm) {
 0232      _threatSwarmMap[threat] = swarmTuple;
 0233    }
 0234    OnThreatSwarmChanged?.Invoke(_threatSwarms);
 0235  }
 236
 0237  public Vector3 GetAllAgentsCenter() {
 0238    List<Agent> allAgents = _interceptorObjects.ConvertAll(interceptor => interceptor as Agent)
 0239                                .Concat(_threatObjects.ConvertAll(threat => threat as Agent))
 240                                .ToList();
 0241    return GetSwarmCenter(allAgents);
 0242  }
 243
 0244  public Vector3 GetSwarmCenter(List<Agent> swarm) {
 0245    if (swarm.Count == 0) {
 0246      return Vector3.zero;
 247    }
 248
 0249    Vector3 sum = Vector3.zero;
 0250    int count = 0;
 0251    int swarmCount = swarm.Count;
 252
 0253    for (int i = 0; i < swarmCount; ++i) {
 0254      Agent agent = swarm[i];
 0255      if (!agent.IsTerminated()) {
 0256        sum += agent.transform.position;
 0257        ++count;
 0258      }
 0259    }
 260
 0261    return count > 0 ? sum / count : Vector3.zero;
 0262  }
 263
 0264  public List<List<(Agent, bool)>> GetInterceptorSwarms() {
 0265    return _interceptorSwarms;
 0266  }
 267
 0268  public List<List<(Agent, bool)>> GetSubmunitionsSwarms() {
 0269    return _submunitionsSwarms;
 0270  }
 271
 0272  public List<List<(Agent, bool)>> GetThreatSwarms() {
 0273    return _threatSwarms;
 0274  }
 275
 0276  public void DestroyInterceptorInSwarm(Interceptor interceptor) {
 0277    var swarm = _interceptorSwarmMap[interceptor];
 0278    int index = swarm.FindIndex(tuple => tuple.Item1 == interceptor);
 0279    if (index != -1) {
 0280      swarm[index] = (swarm[index].Item1, false);
 0281      OnInterceptorSwarmChanged?.Invoke(_interceptorSwarms);
 0282    } else {
 0283      Debug.LogError("Interceptor not found in swarm.");
 0284    }
 0285    if (swarm.All(tuple => !tuple.Item2)) {
 286      // Need to give the camera controller a way to update to the next swarm if it exists.
 0287      if (CameraController.Instance.cameraMode == CameraMode.FOLLOW_INTERCEPTOR_SWARM) {
 0288        CameraController.Instance.FollowNextInterceptorSwarm();
 0289      }
 0290    }
 291
 292    // If this also happens to be a submunition, destroy it in the submunition swarm.
 0293    if (_submunitionsSwarmMap.ContainsKey(interceptor)) {
 0294      DestroySubmunitionInSwarm(interceptor);
 0295    }
 0296  }
 297
 0298  public void DestroySubmunitionInSwarm(Interceptor submunition) {
 0299    var swarm = _submunitionsSwarmMap[submunition];
 0300    int index = swarm.FindIndex(tuple => tuple.Item1 == submunition);
 0301    if (index != -1) {
 0302      swarm[index] = (swarm[index].Item1, false);
 0303      OnSubmunitionsSwarmChanged?.Invoke(_submunitionsSwarms);
 0304    }
 0305  }
 306
 0307  public void DestroyThreatInSwarm(Threat threat) {
 0308    var swarm = _threatSwarmMap[threat];
 0309    int index = swarm.FindIndex(tuple => tuple.Item1 == threat);
 0310    if (index != -1) {
 0311      swarm[index] = (swarm[index].Item1, false);
 0312      OnThreatSwarmChanged?.Invoke(_threatSwarms);
 0313    }
 0314    if (swarm.All(tuple => !tuple.Item2)) {
 0315      _threatSwarms.Remove(swarm);
 0316      if (CameraController.Instance.cameraMode == CameraMode.FOLLOW_THREAT_SWARM) {
 0317        CameraController.Instance.FollowNextThreatSwarm();
 0318      }
 0319    }
 0320  }
 321
 0322  public void RegisterInterceptorHit(Interceptor interceptor, Threat threat) {
 0323    _costDestroyedThreats += threat.staticConfig.Cost;
 0324    if (interceptor is Interceptor missileComponent) {
 0325      _activeInterceptors.Remove(missileComponent);
 0326    }
 0327    DestroyInterceptorInSwarm(interceptor);
 0328    DestroyThreatInSwarm(threat);
 0329  }
 330
 0331  public void RegisterInterceptorMiss(Interceptor interceptor, Threat threat) {
 0332    if (interceptor is Interceptor missileComponent) {
 0333      _activeInterceptors.Remove(missileComponent);
 0334    }
 0335    DestroyInterceptorInSwarm(interceptor);
 0336  }
 337
 0338  public void RegisterThreatHit(Threat threat) {
 0339    DestroyThreatInSwarm(threat);
 0340  }
 341
 0342  public void RegisterThreatMiss(Threat threat) {
 0343    DestroyThreatInSwarm(threat);
 0344  }
 345
 15346  private AttackBehavior LoadAttackBehavior(Configs.AgentConfig config) {
 15347    string attackBehaviorConfigFile = config.AttackBehaviorConfigFile;
 15348    if (string.IsNullOrEmpty(attackBehaviorConfigFile)) {
 0349      return null;
 350    }
 15351    Configs.AttackBehaviorConfig attackBehaviorConfig =
 352        ConfigLoader.LoadAttackBehaviorConfig(attackBehaviorConfigFile);
 15353    return AttackBehaviorFactory.Create(attackBehaviorConfig);
 15354  }
 355
 17356  public Agent CreateDummyAgent(Vector3 position, Vector3 velocity) {
 26357    if (_dummyAgentTable.ContainsKey((position, velocity))) {
 9358      return _dummyAgentTable[(position, velocity)].GetComponent<Agent>();
 359    }
 8360    GameObject dummyAgentPrefab = Resources.Load<GameObject>($"Prefabs/DummyAgent");
 8361    GameObject dummyAgentObject = Instantiate(dummyAgentPrefab, position, Quaternion.identity);
 16362    if (!dummyAgentObject.TryGetComponent<Agent>(out _)) {
 8363      dummyAgentObject.AddComponent<DummyAgent>();
 8364    }
 8365    Rigidbody dummyRigidbody = dummyAgentObject.GetComponent<Rigidbody>();
 8366    dummyRigidbody.linearVelocity = velocity;
 8367    _dummyAgentObjects.Add(dummyAgentObject);
 8368    _dummyAgentTable[(position, velocity)] = dummyAgentObject;
 8369    return dummyAgentObject.GetComponent<Agent>();
 17370  }
 371
 372  // Creates a interceptor based on the provided configuration.
 373  // Returns the created interceptor instance, or null if creation failed.
 1374  public Interceptor CreateInterceptor(Configs.AgentConfig config, Simulation.State initialState) {
 1375    if (config == null) {
 0376      return null;
 377    }
 378
 379    // Load the static configuration for the interceptor.
 1380    Configs.StaticConfig staticConfig = ConfigLoader.LoadStaticConfig(config.ConfigFile);
 1381    if (staticConfig == null) {
 0382      return null;
 383    }
 384
 385    // Create an agent corresponding to the interceptor.
 1386    GameObject interceptorObject = null;
 2387    if (AgentTypePrefabMap.TryGetValue(staticConfig.AgentType, out var prefab)) {
 1388      interceptorObject = CreateAgent(config, initialState, prefab);
 1389    }
 1390    if (interceptorObject == null) {
 0391      return null;
 392    }
 393
 394    // Create a sensor for the interceptor.
 1395    switch (config.DynamicConfig.SensorConfig.Type) {
 1396      case Simulation.SensorType.Ideal: {
 1397        interceptorObject.AddComponent<IdealSensor>();
 1398        break;
 399      }
 0400      default: {
 0401        Debug.LogError($"Sensor type {config.DynamicConfig.SensorConfig.Type} not found.");
 0402        break;
 403      }
 404    }
 405
 1406    Interceptor interceptor = interceptorObject.GetComponent<Interceptor>();
 1407    _interceptorObjects.Add(interceptor);
 1408    _activeInterceptors.Add(interceptor);
 409
 410    // Set the static configuration.
 1411    interceptor.SetStaticConfig(staticConfig);
 412
 413    // Subscribe events.
 1414    interceptor.OnInterceptHit += RegisterInterceptorHit;
 1415    interceptor.OnInterceptMiss += RegisterInterceptorMiss;
 416
 417    // Assign a unique and simple ID.
 1418    int interceptorId = _interceptorObjects.Count;
 1419    interceptorObject.name = $"{staticConfig.Name}_Interceptor_{interceptorId}";
 420
 421    // Add the interceptor's unit cost to the total cost.
 1422    _costLaunchedInterceptors += staticConfig.Cost;
 423
 424    // Let listeners know a new interceptor has been created.
 1425    OnNewInterceptor?.Invoke(interceptor);
 426
 1427    return interceptor;
 1428  }
 429
 430  // Creates a threat based on the provided configuration.
 431  // Returns the created threat instance, or null if creation failed.
 15432  public Threat CreateThreat(Configs.AgentConfig config) {
 15433    if (config == null) {
 0434      return null;
 435    }
 436
 437    // Load the static configuration for the threat.
 15438    Configs.StaticConfig staticConfig = ConfigLoader.LoadStaticConfig(config.ConfigFile);
 15439    if (staticConfig == null) {
 0440      return null;
 441    }
 442
 443    // Create an agent corresponding to the threat.
 15444    GameObject threatObject = null;
 30445    if (AgentTypePrefabMap.TryGetValue(staticConfig.AgentType, out var prefab)) {
 15446      threatObject = CreateRandomAgent(config, prefab);
 15447    }
 15448    if (threatObject == null) {
 0449      return null;
 450    }
 451
 15452    Threat threat = threatObject.GetComponent<Threat>();
 15453    _threatObjects.Add(threat);
 454
 455    // Set the static configuration.
 15456    threat.SetStaticConfig(staticConfig);
 457
 458    // Set the attack behavior.
 15459    AttackBehavior attackBehavior = LoadAttackBehavior(config);
 15460    threat.SetAttackBehavior(attackBehavior);
 461
 462    // Subscribe events.
 15463    threat.OnThreatHit += RegisterThreatHit;
 15464    threat.OnThreatMiss += RegisterThreatMiss;
 465
 466    // Assign a unique and simple ID.
 15467    int threatId = _threatObjects.Count;
 15468    threatObject.name = $"{staticConfig.Name}_Threat_{threatId}";
 469
 470    // Let listeners know that a new threat has been created.
 15471    OnNewThreat?.Invoke(threat);
 472
 15473    return threatObject.GetComponent<Threat>();
 15474  }
 475
 476  // Creates a agent based on the provided configuration and prefab name.
 477  // Returns the created GameObject instance, or null if creation failed.
 478  public GameObject CreateAgent(Configs.AgentConfig config, Simulation.State initialState,
 16479                                string prefabName) {
 16480    GameObject prefab = Resources.Load<GameObject>($"Prefabs/{prefabName}");
 16481    if (prefab == null) {
 0482      Debug.LogError($"Prefab {prefabName} not found in Resources/Prefabs directory.");
 0483      return null;
 484    }
 485
 486    // Set the position.
 16487    GameObject agentObject =
 488        Instantiate(prefab, Coordinates3.FromProto(initialState.Position), Quaternion.identity);
 489
 490    // Set the velocity. The rigid body is frozen while the agent is in the initialized phase.
 16491    agentObject.GetComponent<Agent>().SetInitialVelocity(
 492        Coordinates3.FromProto(initialState.Velocity));
 493
 494    // Set the rotation to face the initial velocity.
 16495    Vector3 velocityDirection = Coordinates3.FromProto(initialState.Velocity).normalized;
 16496    Quaternion targetRotation = Quaternion.LookRotation(velocityDirection, Vector3.up);
 16497    agentObject.transform.rotation = targetRotation;
 498
 16499    agentObject.GetComponent<Agent>().SetAgentConfig(config);
 16500    return agentObject;
 16501  }
 502
 503  // Creates a random agent based on the provided configuration and prefab name.
 504  // Returns the created GameObject instance, or null if creation failed.
 15505  public GameObject CreateRandomAgent(Configs.AgentConfig config, string prefabName) {
 15506    if (config == null) {
 0507      return null;
 508    }
 509
 15510    GameObject prefab = Resources.Load<GameObject>($"Prefabs/{prefabName}");
 15511    if (prefab == null) {
 0512      Debug.LogError($"Prefab {prefabName} not found in Resources/Prefabs directory.");
 0513      return null;
 514    }
 515
 516    // Randomize the initial state.
 15517    Simulation.State initialState = new Simulation.State();
 518
 519    // Randomize the position.
 15520    Vector3 positionNoise = Utilities.GenerateRandomNoise(config.StandardDeviation.Position);
 15521    initialState.Position =
 522        Coordinates3.ToProto(Coordinates3.FromProto(config.InitialState.Position) + positionNoise);
 523
 524    // Randomize the velocity.
 15525    Vector3 velocityNoise = Utilities.GenerateRandomNoise(config.StandardDeviation.Velocity);
 15526    initialState.Velocity =
 527        Coordinates3.ToProto(Coordinates3.FromProto(config.InitialState.Velocity) + velocityNoise);
 15528    return CreateAgent(config, initialState, prefabName);
 15529  }
 530
 0531  public void LoadNewConfig(string configFile) {
 0532    SimulationConfig = ConfigLoader.LoadSimulationConfig(configFile);
 533    // Reload the simulator configuration.
 0534    SimulatorConfig = ConfigLoader.LoadSimulatorConfig();
 0535    if (SimulationConfig != null) {
 0536      Debug.Log($"Loaded new configuration: {configFile}.");
 0537      RestartSimulation();
 0538    } else {
 0539      Debug.LogError($"Failed to load configuration: {configFile}.");
 0540    }
 0541  }
 542
 0543  public void RestartSimulation() {
 0544    OnSimulationEnded?.Invoke();
 0545    Debug.Log("Simulation ended.");
 0546    UIManager.Instance.LogActionMessage("[SIM] Simulation restarted.");
 547    // Reset the simulation time.
 0548    _elapsedSimulationTime = 0f;
 0549    _isSimulationPaused = IsSimulationPaused();
 0550    _costLaunchedInterceptors = 0f;
 0551    _costDestroyedThreats = 0f;
 552
 553    // Clear existing interceptors and threats.
 0554    foreach (var interceptor in _interceptorObjects) {
 0555      if (interceptor != null) {
 0556        Destroy(interceptor.gameObject);
 0557      }
 0558    }
 559
 0560    foreach (var threat in _threatObjects) {
 0561      if (threat != null) {
 0562        Destroy(threat.gameObject);
 0563      }
 0564    }
 565
 0566    foreach (var dummyAgent in _dummyAgentObjects) {
 0567      if (dummyAgent != null) {
 0568        Destroy(dummyAgent);
 0569      }
 0570    }
 571
 0572    _interceptorObjects.Clear();
 0573    _activeInterceptors.Clear();
 0574    _threatObjects.Clear();
 0575    _dummyAgentObjects.Clear();
 0576    _dummyAgentTable.Clear();
 0577    _interceptorSwarms.Clear();
 0578    _submunitionsSwarms.Clear();
 0579    _threatSwarms.Clear();
 0580    OnInterceptorSwarmChanged?.Invoke(_interceptorSwarms);
 0581    OnSubmunitionsSwarmChanged?.Invoke(_submunitionsSwarms);
 0582    OnThreatSwarmChanged?.Invoke(_threatSwarms);
 0583    StartSimulation();
 0584  }
 585
 0586  void FixedUpdate() {
 0587    if (!_isSimulationPaused && _elapsedSimulationTime < SimulationConfig.EndTime) {
 0588      _elapsedSimulationTime += Time.deltaTime;
 0589    } else if (_elapsedSimulationTime >= SimulationConfig.EndTime) {
 0590      RestartSimulation();
 0591      Debug.Log("Simulation completed.");
 0592    }
 0593  }
 594
 0595  public void QuitSimulation() {
 0596    Application.Quit();
 0597  }
 598}

Methods/Properties

SimManager()
Instance()
Instance(SimManager)
SimManager()
GetElapsedSimulationTime()
GetCostLaunchedInterceptors()
GetCostDestroyedThreats()
GetActiveInterceptors()
GetActiveThreats()
GetActiveAgents()
GenerateSwarmTitle(System.Collections.Generic.List[ValueTuple`2], System.Int32)
GenerateInterceptorSwarmTitle(System.Collections.Generic.List[ValueTuple`2])
GenerateSubmunitionsSwarmTitle(System.Collections.Generic.List[ValueTuple`2])
GenerateThreatSwarmTitle(System.Collections.Generic.List[ValueTuple`2])
Awake()
Start()
Update()
SetTimeScale(System.Single)
StartSimulation()
PauseSimulation()
ResumeSimulation()
IsSimulationPaused()
InitializeSimulation()
AddInterceptorSwarm(System.Collections.Generic.List[Agent])
AddSubmunitionsSwarm(System.Collections.Generic.List[Agent])
LookupSubmunitionSwarmIndexInInterceptorSwarm(System.Collections.Generic.List[ValueTuple`2])
AddThreatSwarm(System.Collections.Generic.List[Agent])
GetAllAgentsCenter()
GetSwarmCenter(System.Collections.Generic.List[Agent])
GetInterceptorSwarms()
GetSubmunitionsSwarms()
GetThreatSwarms()
DestroyInterceptorInSwarm(Interceptor)
DestroySubmunitionInSwarm(Interceptor)
DestroyThreatInSwarm(Threat)
RegisterInterceptorHit(Interceptor, Threat)
RegisterInterceptorMiss(Interceptor, Threat)
RegisterThreatHit(Threat)
RegisterThreatMiss(Threat)
LoadAttackBehavior(Configs.AgentConfig)
CreateDummyAgent(UnityEngine.Vector3, UnityEngine.Vector3)
CreateInterceptor(Configs.AgentConfig, Simulation.State)
CreateThreat(Configs.AgentConfig)
CreateAgent(Configs.AgentConfig, Simulation.State, System.String)
CreateRandomAgent(Configs.AgentConfig, System.String)
LoadNewConfig(System.String)
RestartSimulation()
FixedUpdate()
QuitSimulation()