< Summary

Class:SimManager
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Managers/SimManager.cs
Covered lines:203
Uncovered lines:184
Coverable lines:387
Total lines:598
Line coverage:52.4% (203 of 387)
Covered branches:0
Total branches:0
Covered methods:27
Total methods:49
Method coverage:55.1% (27 of 49)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SimManager()0%110100%
SimManager()0%110100%
GetElapsedSimulationTime()0%110100%
GetCostLaunchedInterceptors()0%110100%
GetCostDestroyedThreats()0%110100%
GetActiveInterceptors()0%2100%
GetActiveThreats()0%220100%
GetActiveAgents()0%330100%
GenerateSwarmTitle(...)0%2100%
GenerateInterceptorSwarmTitle(...)0%2100%
GenerateSubmunitionsSwarmTitle(...)0%2100%
GenerateThreatSwarmTitle(...)0%2100%
Awake()0%2.062075%
Start()0%220100%
Update()0%110100%
SetTimeScale(...)0%110100%
StartSimulation()0%220100%
PauseSimulation()0%110100%
ResumeSimulation()0%110100%
IsSimulationPaused()0%110100%
InitializeSimulation()0%550100%
AddInterceptorSwarm(...)0%20400%
AddSubmunitionsSwarm(...)0%20400%
LookupSubmunitionSwarmIndexInInterceptorSwarm(...)0%6200%
AddThreatSwarm(...)0%440100%
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%56700%
CreateThreat(...)0%6.356078.57%
CreateAgent(...)0%2.042078.57%
CreateRandomAgent(...)0%3.273068.75%
LoadNewConfig(...)0%2.062075%
RestartSimulation()0%11.3111086.27%
FixedUpdate()0%4.774063.64%
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.
 111  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.
 859619  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
 230  private List<Interceptor> _activeInterceptors = new List<Interceptor>();
 231  private List<Interceptor> _interceptorObjects = new List<Interceptor>();
 232  private List<Threat> _threatObjects = new List<Threat>();
 33
 234  private List<GameObject> _dummyAgentObjects = new List<GameObject>();
 235  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).
 240  private List<List<(Agent, bool)>> _interceptorSwarms = new List<List<(Agent, bool)>>();
 241  private List<List<(Agent, bool)>> _submunitionsSwarms = new List<List<(Agent, bool)>>();
 242  private List<List<(Agent, bool)>> _threatSwarms = new List<List<(Agent, bool)>>();
 43
 244  private Dictionary<Agent, List<(Agent, bool)>> _interceptorSwarmMap =
 45      new Dictionary<Agent, List<(Agent, bool)>>();
 46
 247  private Dictionary<Agent, List<(Agent, bool)>> _submunitionsSwarmMap =
 48      new Dictionary<Agent, List<(Agent, bool)>>();
 249  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.
 253  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
 262  private float _elapsedSimulationTime = 0f;
 263  private bool _isSimulationPaused = false;
 64
 265  private float _costLaunchedInterceptors = 0f;
 266  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.
 677079  public double GetElapsedSimulationTime() {
 677080    return _elapsedSimulationTime;
 677081  }
 82
 83  // Returns the total cost of launched interceptors.
 2884  public double GetCostLaunchedInterceptors() {
 2885    return _costLaunchedInterceptors;
 2886  }
 87
 88  // Returns the total cost of destroyed threats.
 2889  public double GetCostDestroyedThreats() {
 2890    return _costDestroyedThreats;
 2891  }
 92
 093  public List<Interceptor> GetActiveInterceptors() {
 094    return _activeInterceptors;
 095  }
 96
 497  public List<Threat> GetActiveThreats() {
 56898    return _threatObjects.Where(threat => !threat.IsTerminated()).ToList();
 499  }
 100
 4101  public List<Agent> GetActiveAgents() {
 4102    return _activeInterceptors.ConvertAll(interceptor => interceptor as Agent)
 564103        .Concat(GetActiveThreats().ConvertAll(threat => threat as Agent))
 104        .ToList();
 4105  }
 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
 1126  void Awake() {
 127    // Ensure that only one instance of SimManager exists.
 2128    if (Instance == null) {
 1129      Instance = this;
 1130      DontDestroyOnLoad(gameObject);
 1131    } else {
 0132      Destroy(gameObject);
 0133    }
 1134    SimulationConfig = ConfigLoader.LoadSimulationConfig(_defaultConfig);
 1135    SimulatorConfig = ConfigLoader.LoadSimulatorConfig();
 1136  }
 137
 1138  void Start() {
 2139    if (Instance == this) {
 1140      _isSimulationPaused = false;
 1141      StartSimulation();
 1142      ResumeSimulation();
 1143    }
 1144  }
 145
 56146  void Update() {}
 147
 15148  public void SetTimeScale(float timeScale) {
 15149    Time.timeScale = timeScale;
 150    // Time.fixedDeltaTime is derived from the simulator configuration.
 15151    Time.maximumDeltaTime = Time.fixedDeltaTime * 3;
 15152  }
 153
 10154  public void StartSimulation() {
 10155    InitializeSimulation();
 156
 157    // Invoke the simulation started event to let listeners know to invoke their own handler
 158    // behavior.
 10159    UIManager.Instance.LogActionMessage("[SIM] Simulation started.");
 10160    OnSimulationStarted?.Invoke();
 10161  }
 162
 4163  public void PauseSimulation() {
 4164    SetTimeScale(0);
 4165    Time.fixedDeltaTime = 0;
 4166    _isSimulationPaused = true;
 4167  }
 168
 5169  public void ResumeSimulation() {
 5170    Time.fixedDeltaTime = (float)(1.0f / SimulatorConfig.PhysicsUpdateRate);
 5171    SetTimeScale(SimulationConfig.TimeScale);
 5172    _isSimulationPaused = false;
 5173  }
 174
 19175  public bool IsSimulationPaused() {
 19176    return _isSimulationPaused;
 19177  }
 178
 10179  private void InitializeSimulation() {
 16180    if (!IsSimulationPaused()) {
 181      // If the simulation was not paused, we need to update the time scale.
 6182      SetTimeScale(SimulationConfig.TimeScale);
 6183      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.
 6186    }
 187
 188    // Create threats based on the configuration.
 10189    List<Agent> targets = new List<Agent>();
 126190    foreach (var swarmConfig in SimulationConfig.ThreatSwarmConfigs) {
 32191      List<Agent> swarm = new List<Agent>();
 2329192      for (int i = 0; i < swarmConfig.NumAgents; ++i) {
 755193        Threat threat = CreateThreat(swarmConfig.AgentConfig);
 755194        swarm.Add(threat);
 755195      }
 32196      AddThreatSwarm(swarm);
 32197    }
 10198  }
 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
 32228  public void AddThreatSwarm(List<Agent> swarm) {
 787229    List<(Agent, bool)> swarmTuple = swarm.ConvertAll(agent => (agent, true));
 32230    _threatSwarms.Add(swarmTuple);
 2361231    foreach (var threat in swarm) {
 755232      _threatSwarmMap[threat] = swarmTuple;
 755233    }
 32234    OnThreatSwarmChanged?.Invoke(_threatSwarms);
 32235  }
 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
 755346  private AttackBehavior LoadAttackBehavior(Configs.AgentConfig config) {
 755347    string attackBehaviorConfigFile = config.AttackBehaviorConfigFile;
 755348    if (string.IsNullOrEmpty(attackBehaviorConfigFile)) {
 0349      return null;
 350    }
 755351    Configs.AttackBehaviorConfig attackBehaviorConfig =
 352        ConfigLoader.LoadAttackBehaviorConfig(attackBehaviorConfigFile);
 755353    return AttackBehaviorFactory.Create(attackBehaviorConfig);
 755354  }
 355
 932356  public Agent CreateDummyAgent(Vector3 position, Vector3 velocity) {
 1677357    if (_dummyAgentTable.ContainsKey((position, velocity))) {
 745358      return _dummyAgentTable[(position, velocity)].GetComponent<Agent>();
 359    }
 187360    GameObject dummyAgentPrefab = Resources.Load<GameObject>($"Prefabs/DummyAgent");
 187361    GameObject dummyAgentObject = Instantiate(dummyAgentPrefab, position, Quaternion.identity);
 374362    if (!dummyAgentObject.TryGetComponent<Agent>(out _)) {
 187363      dummyAgentObject.AddComponent<DummyAgent>();
 187364    }
 187365    Rigidbody dummyRigidbody = dummyAgentObject.GetComponent<Rigidbody>();
 187366    dummyRigidbody.linearVelocity = velocity;
 187367    _dummyAgentObjects.Add(dummyAgentObject);
 187368    _dummyAgentTable[(position, velocity)] = dummyAgentObject;
 187369    return dummyAgentObject.GetComponent<Agent>();
 932370  }
 371
 372  // Creates a interceptor based on the provided configuration.
 373  // Returns the created interceptor instance, or null if creation failed.
 0374  public Interceptor CreateInterceptor(Configs.AgentConfig config, Simulation.State initialState) {
 0375    if (config == null) {
 0376      return null;
 377    }
 378
 379    // Load the static configuration for the interceptor.
 0380    Configs.StaticConfig staticConfig = ConfigLoader.LoadStaticConfig(config.ConfigFile);
 0381    if (staticConfig == null) {
 0382      return null;
 383    }
 384
 385    // Create an agent corresponding to the interceptor.
 0386    GameObject interceptorObject = null;
 0387    if (AgentTypePrefabMap.TryGetValue(staticConfig.AgentType, out var prefab)) {
 0388      interceptorObject = CreateAgent(config, initialState, prefab);
 0389    }
 0390    if (interceptorObject == null) {
 0391      return null;
 392    }
 393
 394    // Create a sensor for the interceptor.
 0395    switch (config.DynamicConfig.SensorConfig.Type) {
 0396      case Simulation.SensorType.Ideal: {
 0397        interceptorObject.AddComponent<IdealSensor>();
 0398        break;
 399      }
 0400      default: {
 0401        Debug.LogError($"Sensor type {config.DynamicConfig.SensorConfig.Type} not found.");
 0402        break;
 403      }
 404    }
 405
 0406    Interceptor interceptor = interceptorObject.GetComponent<Interceptor>();
 0407    _interceptorObjects.Add(interceptor);
 0408    _activeInterceptors.Add(interceptor);
 409
 410    // Set the static configuration.
 0411    interceptor.SetStaticConfig(staticConfig);
 412
 413    // Subscribe events.
 0414    interceptor.OnInterceptHit += RegisterInterceptorHit;
 0415    interceptor.OnInterceptMiss += RegisterInterceptorMiss;
 416
 417    // Assign a unique and simple ID.
 0418    int interceptorId = _interceptorObjects.Count;
 0419    interceptorObject.name = $"{staticConfig.Name}_Interceptor_{interceptorId}";
 420
 421    // Add the interceptor's unit cost to the total cost.
 0422    _costLaunchedInterceptors += staticConfig.Cost;
 423
 424    // Let listeners know a new interceptor has been created.
 0425    OnNewInterceptor?.Invoke(interceptor);
 426
 0427    return interceptor;
 0428  }
 429
 430  // Creates a threat based on the provided configuration.
 431  // Returns the created threat instance, or null if creation failed.
 755432  public Threat CreateThreat(Configs.AgentConfig config) {
 755433    if (config == null) {
 0434      return null;
 435    }
 436
 437    // Load the static configuration for the threat.
 755438    Configs.StaticConfig staticConfig = ConfigLoader.LoadStaticConfig(config.ConfigFile);
 755439    if (staticConfig == null) {
 0440      return null;
 441    }
 442
 443    // Create an agent corresponding to the threat.
 755444    GameObject threatObject = null;
 1510445    if (AgentTypePrefabMap.TryGetValue(staticConfig.AgentType, out var prefab)) {
 755446      threatObject = CreateRandomAgent(config, prefab);
 755447    }
 755448    if (threatObject == null) {
 0449      return null;
 450    }
 451
 755452    Threat threat = threatObject.GetComponent<Threat>();
 755453    _threatObjects.Add(threat);
 454
 455    // Set the static configuration.
 755456    threat.SetStaticConfig(staticConfig);
 457
 458    // Set the attack behavior.
 755459    AttackBehavior attackBehavior = LoadAttackBehavior(config);
 755460    threat.SetAttackBehavior(attackBehavior);
 461
 462    // Subscribe events.
 755463    threat.OnThreatHit += RegisterThreatHit;
 755464    threat.OnThreatMiss += RegisterThreatMiss;
 465
 466    // Assign a unique and simple ID.
 755467    int threatId = _threatObjects.Count;
 755468    threatObject.name = $"{staticConfig.Name}_Threat_{threatId}";
 469
 470    // Let listeners know that a new threat has been created.
 755471    OnNewThreat?.Invoke(threat);
 472
 755473    return threatObject.GetComponent<Threat>();
 755474  }
 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,
 755479                                string prefabName) {
 755480    GameObject prefab = Resources.Load<GameObject>($"Prefabs/{prefabName}");
 755481    if (prefab == null) {
 0482      Debug.LogError($"Prefab {prefabName} not found in Resources/Prefabs directory.");
 0483      return null;
 484    }
 485
 486    // Set the position.
 755487    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.
 755491    agentObject.GetComponent<Agent>().SetInitialVelocity(
 492        Coordinates3.FromProto(initialState.Velocity));
 493
 494    // Set the rotation to face the initial velocity.
 755495    Vector3 velocityDirection = Coordinates3.FromProto(initialState.Velocity).normalized;
 755496    Quaternion targetRotation = Quaternion.LookRotation(velocityDirection, Vector3.up);
 755497    agentObject.transform.rotation = targetRotation;
 498
 755499    agentObject.GetComponent<Agent>().SetAgentConfig(config);
 755500    return agentObject;
 755501  }
 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.
 755505  public GameObject CreateRandomAgent(Configs.AgentConfig config, string prefabName) {
 755506    if (config == null) {
 0507      return null;
 508    }
 509
 755510    GameObject prefab = Resources.Load<GameObject>($"Prefabs/{prefabName}");
 755511    if (prefab == null) {
 0512      Debug.LogError($"Prefab {prefabName} not found in Resources/Prefabs directory.");
 0513      return null;
 514    }
 515
 516    // Randomize the initial state.
 755517    Simulation.State initialState = new Simulation.State();
 518
 519    // Randomize the position.
 755520    Vector3 positionNoise = Utilities.GenerateRandomNoise(config.StandardDeviation.Position);
 755521    initialState.Position =
 522        Coordinates3.ToProto(Coordinates3.FromProto(config.InitialState.Position) + positionNoise);
 523
 524    // Randomize the velocity.
 755525    Vector3 velocityNoise = Utilities.GenerateRandomNoise(config.StandardDeviation.Velocity);
 755526    initialState.Velocity =
 527        Coordinates3.ToProto(Coordinates3.FromProto(config.InitialState.Velocity) + velocityNoise);
 755528    return CreateAgent(config, initialState, prefabName);
 755529  }
 530
 9531  public void LoadNewConfig(string configFile) {
 9532    SimulationConfig = ConfigLoader.LoadSimulationConfig(configFile);
 533    // Reload the simulator configuration.
 9534    SimulatorConfig = ConfigLoader.LoadSimulatorConfig();
 18535    if (SimulationConfig != null) {
 9536      Debug.Log($"Loaded new configuration: {configFile}.");
 9537      RestartSimulation();
 9538    } else {
 0539      Debug.LogError($"Failed to load configuration: {configFile}.");
 0540    }
 9541  }
 542
 9543  public void RestartSimulation() {
 9544    OnSimulationEnded?.Invoke();
 9545    Debug.Log("Simulation ended.");
 9546    UIManager.Instance.LogActionMessage("[SIM] Simulation restarted.");
 547    // Reset the simulation time.
 9548    _elapsedSimulationTime = 0f;
 9549    _isSimulationPaused = IsSimulationPaused();
 9550    _costLaunchedInterceptors = 0f;
 9551    _costDestroyedThreats = 0f;
 552
 553    // Clear existing interceptors and threats.
 27554    foreach (var interceptor in _interceptorObjects) {
 0555      if (interceptor != null) {
 0556        Destroy(interceptor.gameObject);
 0557      }
 0558    }
 559
 2271560    foreach (var threat in _threatObjects) {
 1496561      if (threat != null) {
 748562        Destroy(threat.gameObject);
 748563      }
 748564    }
 565
 579566    foreach (var dummyAgent in _dummyAgentObjects) {
 368567      if (dummyAgent != null) {
 184568        Destroy(dummyAgent);
 184569      }
 184570    }
 571
 9572    _interceptorObjects.Clear();
 9573    _activeInterceptors.Clear();
 9574    _threatObjects.Clear();
 9575    _dummyAgentObjects.Clear();
 9576    _dummyAgentTable.Clear();
 9577    _interceptorSwarms.Clear();
 9578    _submunitionsSwarms.Clear();
 9579    _threatSwarms.Clear();
 9580    OnInterceptorSwarmChanged?.Invoke(_interceptorSwarms);
 9581    OnSubmunitionsSwarmChanged?.Invoke(_submunitionsSwarms);
 9582    OnThreatSwarmChanged?.Invoke(_threatSwarms);
 9583    StartSimulation();
 9584  }
 585
 91586  void FixedUpdate() {
 164587    if (!_isSimulationPaused && _elapsedSimulationTime < SimulationConfig.EndTime) {
 73588      _elapsedSimulationTime += Time.deltaTime;
 91589    } else if (_elapsedSimulationTime >= SimulationConfig.EndTime) {
 0590      RestartSimulation();
 0591      Debug.Log("Simulation completed.");
 0592    }
 91593  }
 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()