From 0c7d69d6323b45d7e2997ff77158ca7212afb622 Mon Sep 17 00:00:00 2001 From: Daniel Lovell Date: Tue, 1 Oct 2024 19:10:47 -0700 Subject: [PATCH] IADS split out from SimManager IADS handles the threattable and assigning targets IADS now implements batched threat assignments --- Assets/Materials/DroneTargetMat.mat | 5 +- Assets/Scenes/MainScene.unity | 165 +++++++++++++++++++++---- Assets/Scripts/IADS/IADS.cs | 144 ++++++++++++++++++--- Assets/Scripts/Interceptors/Hydra70.cs | 2 +- Assets/Scripts/SimManager.cs | 88 +++++-------- 5 files changed, 306 insertions(+), 98 deletions(-) diff --git a/Assets/Materials/DroneTargetMat.mat b/Assets/Materials/DroneTargetMat.mat index 3f608c3..6b9e8a0 100644 --- a/Assets/Materials/DroneTargetMat.mat +++ b/Assets/Materials/DroneTargetMat.mat @@ -98,6 +98,7 @@ Material: m_Offset: {x: 0, y: 0} m_Ints: [] m_Floats: + - _AddPrecomputedVelocity: 0 - _AlphaClip: 0 - _AlphaToMask: 0 - _Blend: 0 @@ -135,8 +136,8 @@ Material: - _WorkflowMode: 1 - _ZWrite: 1 m_Colors: - - _BaseColor: {r: 1, g: 0, b: 0, a: 1} - - _Color: {r: 1, g: 0, b: 0, a: 1} + - _BaseColor: {r: 0.6679245, g: 0, b: 0, a: 1} + - _Color: {r: 0.66792446, g: 0, b: 0, a: 1} - _EmissionColor: {r: 0.9622642, g: 0, b: 0, a: 1} - _SpecColor: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} m_BuildTextureStacks: [] diff --git a/Assets/Scenes/MainScene.unity b/Assets/Scenes/MainScene.unity index def311f..3e29ec1 100644 --- a/Assets/Scenes/MainScene.unity +++ b/Assets/Scenes/MainScene.unity @@ -13,7 +13,7 @@ OcclusionCullingSettings: --- !u!104 &2 RenderSettings: m_ObjectHideFlags: 0 - serializedVersion: 9 + serializedVersion: 10 m_Fog: 0 m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_FogMode: 3 @@ -43,7 +43,6 @@ RenderSettings: LightmapSettings: m_ObjectHideFlags: 0 serializedVersion: 12 - m_GIWorkflowMode: 1 m_GISettings: serializedVersion: 2 m_BounceScale: 1 @@ -66,9 +65,6 @@ LightmapSettings: m_LightmapParameters: {fileID: 0} m_LightmapsBakeMode: 1 m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 m_ReflectionCompression: 2 m_MixedBakeMode: 2 m_BakeBackend: 1 @@ -207,9 +203,8 @@ Light: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 50643631} m_Enabled: 1 - serializedVersion: 10 + serializedVersion: 11 m_Type: 1 - m_Shape: 0 m_Color: {r: 1, g: 1, b: 1, a: 1} m_Intensity: 0.75 m_Range: 10 @@ -259,8 +254,12 @@ Light: m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} m_UseBoundingSphereOverride: 0 m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 m_ShadowRadius: 0 m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 --- !u!4 &50643634 Transform: m_ObjectHideFlags: 0 @@ -349,6 +348,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -455,6 +457,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -561,6 +566,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -667,6 +675,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -863,6 +874,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -996,15 +1010,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -1103,6 +1119,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -1419,14 +1438,18 @@ MonoBehaviour: m_ItemText: {fileID: 1985109736} m_ItemImage: {fileID: 0} m_Value: 0 + m_MultiSelect: 0 m_Options: m_Options: - m_Text: Option A m_Image: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} - m_Text: Option B m_Image: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} - m_Text: Option C m_Image: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} m_OnValueChanged: m_PersistentCalls: m_Calls: [] @@ -1569,15 +1592,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -1703,15 +1728,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 0 m_isCullingEnabled: 0 @@ -1749,6 +1776,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -1851,6 +1881,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -1933,9 +1966,8 @@ Light: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 396716023} m_Enabled: 1 - serializedVersion: 10 + serializedVersion: 11 m_Type: 1 - m_Shape: 0 m_Color: {r: 1, g: 1, b: 1, a: 1} m_Intensity: 0.75 m_Range: 10 @@ -1985,8 +2017,12 @@ Light: m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} m_UseBoundingSphereOverride: 0 m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 m_ShadowRadius: 0 m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 --- !u!4 &396716026 Transform: m_ObjectHideFlags: 0 @@ -2075,6 +2111,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -2185,6 +2224,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -2298,9 +2340,8 @@ Light: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 566761696} m_Enabled: 1 - serializedVersion: 10 + serializedVersion: 11 m_Type: 1 - m_Shape: 0 m_Color: {r: 1, g: 1, b: 1, a: 1} m_Intensity: 0.75 m_Range: 10 @@ -2350,8 +2391,12 @@ Light: m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} m_UseBoundingSphereOverride: 0 m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 m_ShadowRadius: 0 m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 --- !u!4 &566761699 Transform: m_ObjectHideFlags: 0 @@ -2474,15 +2519,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -3022,15 +3069,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 0 m_isCullingEnabled: 0 @@ -3068,6 +3117,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -3268,15 +3320,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -3410,6 +3464,51 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1071150555} m_CullTransparentMesh: 1 +--- !u!1 &1134242713 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1134242715} + - component: {fileID: 1134242714} + m_Layer: 0 + m_Name: IADS + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1134242714 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1134242713} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a5899f1049cf3d64e8c06c1db772c879, type: 3} + m_Name: + m_EditorClassIdentifier: + _threatTable: [] +--- !u!4 &1134242715 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1134242713} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1254435375 GameObject: m_ObjectHideFlags: 0 @@ -3478,6 +3577,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -3599,6 +3701,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -3732,15 +3837,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 0 m_isCullingEnabled: 0 @@ -3778,6 +3885,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4207,15 +4317,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -4389,6 +4501,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4611,15 +4726,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 0 m_isCullingEnabled: 0 @@ -4657,6 +4774,9 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4858,15 +4978,17 @@ MonoBehaviour: m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 + m_TextWrappingMode: 1 m_wordWrappingRatios: 0.4 m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 + m_ActiveFontFeatures: 00000000 m_enableExtraPadding: 0 checkPaddingRequired: 0 m_isRichText: 1 + m_EmojiFallbackSupport: 1 m_parseCtrlCharacters: 1 m_isOrthographic: 1 m_isCullingEnabled: 0 @@ -5461,3 +5583,4 @@ SceneRoots: - {fileID: 566761699} - {fileID: 50643634} - {fileID: 396716026} + - {fileID: 1134242715} diff --git a/Assets/Scripts/IADS/IADS.cs b/Assets/Scripts/IADS/IADS.cs index 27da001..e7b525c 100644 --- a/Assets/Scripts/IADS/IADS.cs +++ b/Assets/Scripts/IADS/IADS.cs @@ -1,30 +1,146 @@ using UnityEngine; -using System.Collections.Generic; -using System.Collections; using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; // Integrated Air Defense System public class IADS : MonoBehaviour { - public enum TargetStatus { UNASSIGNED, ASSIGNED, HIT, DEGRADED, DESTROYED } - // Look up threat status by unique threat ID - public Dictionary _targetStatusDictionary; + public enum ThreatAssignmentStyle { + ONE_TIME, + CONTINUOUS + } - private List _threats; + public static IADS Instance { get; private set; } + private IAssignment _assignmentScheme; + + [SerializeField] + private List _threatTable = new List(); + private Dictionary _threatDataMap = new Dictionary(); - private List _interceptors; + private List _assignentQueue = new List(); - private List _vessels; + private void Awake() { + if (Instance == null) { + Instance = this; + } else { + Destroy(gameObject); + } - public delegate void RegisterNewThreatDelegate(Threat threat); - public event RegisterNewThreatDelegate OnRegisterNewThreat; + } - void Start() { - _threats = new List(); + private void Start() { + SimManager.Instance.OnSimulationEnded += RegisterSimulationEnded; + SimManager.Instance.OnNewThreat += RegisterNewThreat; + SimManager.Instance.OnNewInterceptor += RegisterNewInterceptor; + _assignmentScheme = new ThreatAssignment(); + + } + + public void LateUpdate() { + if (_assignentQueue.Count > 0) { + AssignInterceptorsToThreats(_assignentQueue); + _assignentQueue.Clear(); + } + } + + public void RequestThreatAssignment(List interceptors) { + _assignentQueue.AddRange(interceptors); + } + + public void RequestThreatAssignment(Interceptor interceptor) { + _assignentQueue.Add(interceptor); + } + + + /// + /// Assigns the specified list of missiles to available targets based on the assignment scheme. + /// + /// The list of missiles to assign. + public void AssignInterceptorsToThreats(List missilesToAssign) { + // Perform the assignment + IEnumerable assignments = + _assignmentScheme.Assign(missilesToAssign, _threatTable); + + // Apply the assignments to the missiles + foreach (var assignment in assignments) { + assignment.Interceptor.AssignTarget(assignment.Threat); + _threatDataMap[assignment.Threat].AssignInterceptor(assignment.Interceptor); + Debug.Log($"Interceptor {assignment.Interceptor.name} assigned to threat {assignment.Threat.name}"); + } + + // Check if any interceptors were not assigned + List unassignedInterceptors = missilesToAssign.Where(m => !m.HasAssignedTarget()).ToList(); + + if (unassignedInterceptors.Count > 0) + { + string unassignedIds = string.Join(", ", unassignedInterceptors.Select(m => m.name)); + int totalInterceptors = missilesToAssign.Count; + int assignedInterceptors = totalInterceptors - unassignedInterceptors.Count; + + Debug.LogWarning($"Warning: {unassignedInterceptors.Count} out of {totalInterceptors} interceptors were not assigned to any threat. " + + $"Unassigned interceptor IDs: {unassignedIds}. " + + $"Total interceptors: {totalInterceptors}, Assigned: {assignedInterceptors}, Unassigned: {unassignedInterceptors.Count}"); + + // Log information about the assignment scheme + Debug.Log($"Current Assignment Scheme: {_assignmentScheme.GetType().Name}"); + } } public void RegisterNewThreat(Threat threat) { - _threats.Add(threat); - OnRegisterNewThreat?.Invoke(threat); + ThreatData threatData = new ThreatData(threat, threat.gameObject.name); + _threatTable.Add(threatData); + _threatDataMap.Add(threat, threatData); + + // Subscribe to the threat's events + // TODO: If we do not want omniscient IADS, we + // need to model the IADS's sensors here. + threat.OnInterceptHit += RegisterThreatHit; + threat.OnInterceptMiss += RegisterThreatMiss; } + + public void RegisterNewInterceptor(Interceptor interceptor) { + // Placeholder + interceptor.OnInterceptMiss += RegisterInterceptorMiss; + interceptor.OnInterceptHit += RegisterInterceptorHit; + } + + private void RegisterInterceptorHit(Interceptor interceptor, Threat threat) { + ThreatData threatData = _threatDataMap[threat]; + if (threatData != null) { + threatData.RemoveInterceptor(interceptor); + MarkThreatDestroyed(threatData); + } + } + + private void RegisterInterceptorMiss(Interceptor interceptor, Threat threat) { + // Remove the interceptor from the threat's assigned interceptors + _threatDataMap[threat].RemoveInterceptor(interceptor); + } + private void RegisterThreatHit(Interceptor interceptor, Threat threat) { + ThreatData threatData = _threatDataMap[threat]; + if (threatData != null) { + threatData.RemoveInterceptor(interceptor); + MarkThreatDestroyed(threatData); + } + } + + private void MarkThreatDestroyed(ThreatData threatData) { + if (threatData != null) { + threatData.MarkDestroyed(); + } + } + + private void RegisterThreatMiss(Interceptor interceptor, Threat threat) { + ThreatData threatData = _threatDataMap[threat]; + threatData.RemoveInterceptor(interceptor); + } + + private void RegisterSimulationEnded() { + _threatTable.Clear(); + _threatDataMap.Clear(); + _assignentQueue.Clear(); + } + } \ No newline at end of file diff --git a/Assets/Scripts/Interceptors/Hydra70.cs b/Assets/Scripts/Interceptors/Hydra70.cs index 3507482..0c00a8a 100644 --- a/Assets/Scripts/Interceptors/Hydra70.cs +++ b/Assets/Scripts/Interceptors/Hydra70.cs @@ -48,6 +48,6 @@ public class Hydra70 : Interceptor { } break; } - SimManager.Instance.AssignInterceptorsToThreats(submunitions); + IADS.Instance.RequestThreatAssignment(submunitions); } } diff --git a/Assets/Scripts/SimManager.cs b/Assets/Scripts/SimManager.cs index 515a8ec..e56eabd 100644 --- a/Assets/Scripts/SimManager.cs +++ b/Assets/Scripts/SimManager.cs @@ -21,9 +21,7 @@ public class SimManager : MonoBehaviour { private List _activeInterceptors = new List(); - [SerializeField] - private List _threatTable = new List(); - private Dictionary _threatDataMap = new Dictionary(); + private List _interceptorObjects = new List(); private List _threatObjects = new List(); @@ -32,12 +30,19 @@ public class SimManager : MonoBehaviour { private float endTime = 100f; // Set an appropriate end time private bool simulationRunning = false; - private IAssignment _assignmentScheme; + public delegate void SimulationEventHandler(); public event SimulationEventHandler OnSimulationEnded; public event SimulationEventHandler OnSimulationStarted; + public delegate void NewThreatEventHandler(Threat threat); + public event NewThreatEventHandler OnNewThreat; + + + public delegate void NewInterceptorEventHandler(Interceptor interceptor); + public event NewInterceptorEventHandler OnNewInterceptor; + /// /// Gets the elapsed simulation time. /// @@ -51,7 +56,7 @@ public class SimManager : MonoBehaviour { } public List GetActiveThreats() { - return _threatTable.Where(threat => threat.Status != ThreatStatus.DESTROYED).Select(threat => threat.Threat).ToList(); + return _threatObjects.Where(threat => !threat.IsHit()).ToList(); } public List GetActiveAgents() { @@ -111,7 +116,7 @@ public class SimManager : MonoBehaviour { // Create missiles based on config foreach (var swarmConfig in simulationConfig.interceptor_swarm_configs) { for (int i = 0; i < swarmConfig.num_agents; i++) { - var interceptor = CreateInterceptor(swarmConfig.agent_config); + CreateInterceptor(swarmConfig.agent_config); } } @@ -119,11 +124,10 @@ public class SimManager : MonoBehaviour { // Create targets based on config foreach (var swarmConfig in simulationConfig.threat_swarm_configs) { for (int i = 0; i < swarmConfig.num_agents; i++) { - var threat = CreateThreat(swarmConfig.agent_config); + CreateThreat(swarmConfig.agent_config); } } - _assignmentScheme = new ThreatAssignment(); // Invoke the simulation started event to let listeners // know to invoke their own handler behavior @@ -131,7 +135,7 @@ public class SimManager : MonoBehaviour { } public void AssignInterceptorsToThreats() { - AssignInterceptorsToThreats(_interceptorObjects); + IADS.Instance.AssignInterceptorsToThreats(_interceptorObjects); } public void RegisterInterceptorHit(Interceptor interceptor, Threat threat) { @@ -144,57 +148,18 @@ public class SimManager : MonoBehaviour { if (interceptor is Interceptor missileComponent) { _activeInterceptors.Remove(missileComponent); } - // Remove the interceptor from the threat's assigned interceptors - _threatDataMap[threat].RemoveInterceptor(interceptor); } public void RegisterThreatHit(Interceptor interceptor, Threat threat) { - ThreatData threatData = _threatDataMap[threat]; - threatData.RemoveInterceptor(interceptor); - if (threatData != null) { - threatData.MarkDestroyed(); - } + // Placeholder } public void RegisterThreatMiss(Interceptor interceptor, Threat threat) { Debug.Log($"RegisterThreatMiss: Interceptor {interceptor.name} missed threat {threat.name}"); - ThreatData threatData = _threatDataMap[threat]; - threatData.RemoveInterceptor(interceptor); + // Placeholder } - /// - /// Assigns the specified list of missiles to available targets based on the assignment scheme. - /// - /// The list of missiles to assign. - public void AssignInterceptorsToThreats(List missilesToAssign) { - // Perform the assignment - IEnumerable assignments = - _assignmentScheme.Assign(missilesToAssign, _threatTable); - - // Apply the assignments to the missiles - foreach (var assignment in assignments) { - assignment.Interceptor.AssignTarget(assignment.Threat); - _threatDataMap[assignment.Threat].AssignInterceptor(assignment.Interceptor); - Debug.Log($"Interceptor {assignment.Interceptor.name} assigned to threat {assignment.Threat.name}"); - } - - // Check if any interceptors were not assigned - List unassignedInterceptors = missilesToAssign.Where(m => !m.HasAssignedTarget()).ToList(); - - if (unassignedInterceptors.Count > 0) - { - string unassignedIds = string.Join(", ", unassignedInterceptors.Select(m => m.name)); - int totalInterceptors = missilesToAssign.Count; - int assignedInterceptors = totalInterceptors - unassignedInterceptors.Count; - - Debug.LogWarning($"Warning: {unassignedInterceptors.Count} out of {totalInterceptors} interceptors were not assigned to any threat. " + - $"Unassigned interceptor IDs: {unassignedIds}. " + - $"Total interceptors: {totalInterceptors}, Assigned: {assignedInterceptors}, Unassigned: {unassignedInterceptors.Count}"); - - // Log information about the assignment scheme - Debug.Log($"Current Assignment Scheme: {_assignmentScheme.GetType().Name}"); - } - } + /// /// Creates a interceptor based on the provided configuration. @@ -224,13 +189,18 @@ public class SimManager : MonoBehaviour { _interceptorObjects.Add(interceptor); _activeInterceptors.Add(interceptor); + // Subscribe events interceptor.OnInterceptHit += RegisterInterceptorHit; interceptor.OnInterceptMiss += RegisterInterceptorMiss; // Assign a unique and simple ID - int missileId = _interceptorObjects.Count; - interceptorObject.name = $"{config.interceptor_type}_Interceptor_{missileId}"; + int interceptorId = _interceptorObjects.Count; + interceptorObject.name = $"{config.interceptor_type}_Interceptor_{interceptorId}"; + + // Let listeners know a new interceptor has been created + OnNewInterceptor?.Invoke(interceptor); + return interceptorObject.GetComponent(); } @@ -250,18 +220,19 @@ public class SimManager : MonoBehaviour { Threat threat = threatObject.GetComponent(); // Assign a unique and simple ID - int targetId = _threatTable.Count; + int targetId = _threatObjects.Count; threatObject.name = $"{config.threat_type}_Target_{targetId}"; ThreatData threatData = new ThreatData(threat, threatObject.name); - _threatDataMap.Add(threat, threatData); - _threatTable.Add(threatData); _threatObjects.Add(threat); // Subscribe events threat.OnInterceptHit += RegisterThreatHit; threat.OnInterceptMiss += RegisterThreatMiss; + // Let listeners know a new threat has been created + OnNewThreat?.Invoke(threat); + return threatObject.GetComponent(); } @@ -311,7 +282,7 @@ public class SimManager : MonoBehaviour { _elapsedSimulationTime = 0f; simulationRunning = IsSimulationRunning(); - // Clear existing missiles and targets + // Clear existing interceptors and threats foreach (var interceptor in _interceptorObjects) { if (interceptor != null) { Destroy(interceptor.gameObject); @@ -327,9 +298,6 @@ public class SimManager : MonoBehaviour { _interceptorObjects.Clear(); _activeInterceptors.Clear(); _threatObjects.Clear(); - _threatTable.Clear(); - - StartSimulation(); }