diff --git a/unity-client/Assets.meta b/unity-client/Assets.meta new file mode 100644 index 0000000..2781079 --- /dev/null +++ b/unity-client/Assets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1b2c3d4e5f600001000000000000001 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scenes.meta b/unity-client/Assets/Scenes.meta new file mode 100644 index 0000000..ba69c09 --- /dev/null +++ b/unity-client/Assets/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1b2c3d4e5f600001000000000000006 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scenes/MainScene.unity b/unity-client/Assets/Scenes/MainScene.unity new file mode 100644 index 0000000..84e7558 --- /dev/null +++ b/unity-client/Assets/Scenes/MainScene.unity @@ -0,0 +1,732 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_Compaction: 1 + m_MoveToLightmap: 1 + m_ShadowMaskMode: 1 + m_EnableLightmapDumper: 0 + m_AdaptiveController: + Active: 0 + Min: 0 + Max: 0 + m_AdditionalLightmapResolution: 0 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &100 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Component: + - component: {fileID: 101} + - component: {fileID: 102} + m_Layer: 0 + m_Name: GameManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &101 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 100} + 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_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &102 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 100} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a1b2c3d4e5f600001000000000000001, type: 3} + m_Name: + m_EditorClassIdentifier: + initialBudget: 1000 + initialReputation: 50 + simulationManager: {fileID: 202} + uiManager: {fileID: 305} +--- !u!1 &200 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Component: + - component: {fileID: 201} + - component: {fileID: 202} + m_Layer: 0 + m_Name: SimulationManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &201 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 200} + 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_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &202 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 200} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a1b2c3d4e5f600001000000000000002, type: 3} + m_Name: + m_EditorClassIdentifier: + scenarioFile: {fileID: 0} + timeScale: 1 + uiManager: {fileID: 305} + gameManager: {fileID: 102} +--- !u!1 &300 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Component: + - component: {fileID: 301} + - component: {fileID: 302} + - component: {fileID: 303} + - component: {fileID: 304} + - component: {fileID: 305} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &301 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 300} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 401} + - {fileID: 501} + - {fileID: 601} + - {fileID: 701} + - {fileID: 801} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &302 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 300} + m_Enabled: 1 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!114 &303 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 300} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7954c6130b386c641963172d120fb4ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!114 &304 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 300} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &305 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 300} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a1b2c3d4e5f600001000000000000006, type: 3} + m_Name: + m_EditorClassIdentifier: + timeText: {fileID: 403} + budgetText: {fileID: 503} + reputationText: {fileID: 603} + eventPanelPrefab: {fileID: 800} + popupContainer: {fileID: 701} +--- !u!1 &400 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Component: + - component: {fileID: 401} + - component: {fileID: 402} + - component: {fileID: 403} + m_Layer: 5 + m_Name: TimeText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &401 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 400} + 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_Children: [] + m_Father: {fileID: 301} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 100, y: -50} + m_SizeDelta: {x: 200, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &402 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 400} + m_CullTransparentMesh: 1 +--- !u!114 &403 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 400} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'Time: 00:00:00' +--- !u!1 &500 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Component: + - component: {fileID: 501} + - component: {fileID: 502} + - component: {fileID: 503} + m_Layer: 5 + m_Name: BudgetText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &501 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 500} + 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_Children: [] + m_Father: {fileID: 301} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 1} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: -50} + m_SizeDelta: {x: 200, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &502 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 500} + m_CullTransparentMesh: 1 +--- !u!114 &503 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 500} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'Budget: $0' +--- !u!1 &600 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Component: + - component: {fileID: 601} + - component: {fileID: 602} + - component: {fileID: 603} + m_Layer: 5 + m_Name: ReputationText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &601 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 600} + 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_Children: [] + m_Father: {fileID: 301} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -100, y: -50} + m_SizeDelta: {x: 200, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &602 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 600} + m_CullTransparentMesh: 1 +--- !u!114 &603 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 600} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 2 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 'Reputation: 50%' +--- !u!1 &700 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Component: + - component: {fileID: 701} + m_Layer: 5 + m_Name: PopupContainer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &701 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 700} + 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_Children: [] + m_Father: {fileID: 301} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &800 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Component: + - component: {fileID: 801} + - component: {fileID: 802} + - component: {fileID: 803} + - component: {fileID: 804} + m_Layer: 5 + m_Name: EventPanel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &801 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 800} + 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_Children: [] + m_Father: {fileID: 301} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 300, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &802 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 800} + m_CullTransparentMesh: 1 +--- !u!114 &803 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 800} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &804 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 800} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a1b2c3d4e5f600001000000000000007, type: 3} + m_Name: + m_EditorClassIdentifier: + subjectText: {fileID: 0} + locationText: {fileID: 0} + recipientText: {fileID: 0} + respondButton: {fileID: 0} + ignoreButton: {fileID: 0} +--- !u!1 &1000 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Component: + - component: {fileID: 1001} + - component: {fileID: 1002} + - component: {fileID: 1003} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1001 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1000} + 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_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1002 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1000} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0954073a72a42289647aa583d076770, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!114 &1003 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1000} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48d7e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 diff --git a/unity-client/Assets/Scenes/MainScene.unity.meta b/unity-client/Assets/Scenes/MainScene.unity.meta new file mode 100644 index 0000000..4c12565 --- /dev/null +++ b/unity-client/Assets/Scenes/MainScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f600001000000000000008 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts.meta b/unity-client/Assets/Scripts.meta new file mode 100644 index 0000000..68bcec5 --- /dev/null +++ b/unity-client/Assets/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1b2c3d4e5f600001000000000000002 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/Core.meta b/unity-client/Assets/Scripts/Core.meta new file mode 100644 index 0000000..638c6bf --- /dev/null +++ b/unity-client/Assets/Scripts/Core.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1b2c3d4e5f600001000000000000003 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/Core/GameManager.cs b/unity-client/Assets/Scripts/Core/GameManager.cs new file mode 100644 index 0000000..930fa2b --- /dev/null +++ b/unity-client/Assets/Scripts/Core/GameManager.cs @@ -0,0 +1,47 @@ +using UnityEngine; +using DisasterSimulator.UI; + +namespace DisasterSimulator.Core +{ + public class GameManager : MonoBehaviour + { + public static GameManager Instance { get; private set; } + + [Header("Configuration")] + public float initialBudget = 1000f; + public float initialReputation = 50f; + + [Header("References")] + public SimulationManager simulationManager; + public UIManager uiManager; + + public ResourceManager ResourceManager { get; private set; } + + private void Awake() + { + if (Instance == null) + { + Instance = this; + DontDestroyOnLoad(gameObject); + } + else + { + Destroy(gameObject); + } + + ResourceManager = new ResourceManager(initialBudget, initialReputation); + } + + private void Start() + { + if (uiManager != null) + { + uiManager.UpdateBudget(ResourceManager.Budget); + uiManager.UpdateReputation(ResourceManager.Reputation); + + ResourceManager.OnBudgetChanged += uiManager.UpdateBudget; + ResourceManager.OnReputationChanged += uiManager.UpdateReputation; + } + } + } +} diff --git a/unity-client/Assets/Scripts/Core/GameManager.cs.meta b/unity-client/Assets/Scripts/Core/GameManager.cs.meta new file mode 100644 index 0000000..398362c --- /dev/null +++ b/unity-client/Assets/Scripts/Core/GameManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f600001000000000000001 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/Core/ResourceManager.cs b/unity-client/Assets/Scripts/Core/ResourceManager.cs new file mode 100644 index 0000000..a813b2f --- /dev/null +++ b/unity-client/Assets/Scripts/Core/ResourceManager.cs @@ -0,0 +1,48 @@ +using System; + +namespace DisasterSimulator.Core +{ + public class ResourceManager + { + public float Budget { get; private set; } + public float Reputation { get; private set; } + + public event Action OnBudgetChanged; + public event Action OnReputationChanged; + + public ResourceManager(float initialBudget, float initialReputation) + { + Budget = initialBudget; + Reputation = initialReputation; + } + + public void AddBudget(float amount) + { + Budget += amount; + OnBudgetChanged?.Invoke(Budget); + } + + public bool SpendBudget(float amount) + { + if (Budget >= amount) + { + Budget -= amount; + OnBudgetChanged?.Invoke(Budget); + return true; + } + return false; + } + + public void AddReputation(float amount) + { + Reputation = Math.Min(Reputation + amount, 100); + OnReputationChanged?.Invoke(Reputation); + } + + public void LoseReputation(float amount) + { + Reputation = Math.Max(Reputation - amount, 0); + OnReputationChanged?.Invoke(Reputation); + } + } +} diff --git a/unity-client/Assets/Scripts/Core/ResourceManager.cs.meta b/unity-client/Assets/Scripts/Core/ResourceManager.cs.meta new file mode 100644 index 0000000..fe28ec7 --- /dev/null +++ b/unity-client/Assets/Scripts/Core/ResourceManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f600001000000000000003 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/Core/SimulationManager.cs b/unity-client/Assets/Scripts/Core/SimulationManager.cs new file mode 100644 index 0000000..c0edf40 --- /dev/null +++ b/unity-client/Assets/Scripts/Core/SimulationManager.cs @@ -0,0 +1,101 @@ +using UnityEngine; +using System.Collections.Generic; +using System.IO; +using System.Xml.Serialization; +using DisasterSimulator.Data; +using DisasterSimulator.UI; + +namespace DisasterSimulator.Core +{ + public class SimulationManager : MonoBehaviour + { + [Header("Configuration")] + public TextAsset scenarioFile; + public float timeScale = 1.0f; + + [Header("References")] + public UIManager uiManager; + public GameManager gameManager; + + private Scenario currentScenario; + private float currentTime; + private bool isRunning; + private HashSet triggeredEvents = new HashSet(); + + public float CurrentTime => currentTime; + + void Start() + { + if (scenarioFile != null) + { + LoadScenario(scenarioFile.text); + } + } + + public void LoadScenario(string xmlContent) + { + XmlSerializer serializer = new XmlSerializer(typeof(Scenario)); + using (StringReader reader = new StringReader(xmlContent)) + { + currentScenario = (Scenario)serializer.Deserialize(reader); + } + + currentTime = 0; + triggeredEvents.Clear(); + isRunning = true; + Debug.Log($"Loaded Scenario: {currentScenario.Name}"); + } + + void Update() + { + if (!isRunning || currentScenario == null) return; + + currentTime += Time.deltaTime * timeScale; + + // Update UI time + if (uiManager != null) + { + uiManager.UpdateTime(TimeUtils.FormatTime(currentTime)); + } + + CheckEvents(); + } + + void CheckEvents() + { + if (currentScenario.Events == null) return; + + foreach (var evt in currentScenario.Events) + { + if (triggeredEvents.Contains(evt)) continue; + + float eventTime = TimeUtils.ParseTime(evt.TimeString); + if (currentTime >= eventTime) + { + TriggerEvent(evt); + } + } + } + + void TriggerEvent(Event evt) + { + triggeredEvents.Add(evt); + Debug.Log($"Event Triggered: {evt.Subject} at {evt.Location}"); + + if (uiManager != null) + { + uiManager.ShowEventPopup(evt); + } + } + + public void StopSimulation() + { + isRunning = false; + } + + public void ResumeSimulation() + { + isRunning = true; + } + } +} diff --git a/unity-client/Assets/Scripts/Core/SimulationManager.cs.meta b/unity-client/Assets/Scripts/Core/SimulationManager.cs.meta new file mode 100644 index 0000000..a88c69d --- /dev/null +++ b/unity-client/Assets/Scripts/Core/SimulationManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f600001000000000000002 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/Core/TimeUtils.cs b/unity-client/Assets/Scripts/Core/TimeUtils.cs new file mode 100644 index 0000000..a89e3ef --- /dev/null +++ b/unity-client/Assets/Scripts/Core/TimeUtils.cs @@ -0,0 +1,28 @@ +using System; + +namespace DisasterSimulator.Core +{ + public static class TimeUtils + { + public static float ParseTime(string timeString) + { + if (string.IsNullOrEmpty(timeString)) return 0; + string[] parts = timeString.Split(':'); + if (parts.Length != 3) return 0; + + float hours = float.Parse(parts[0]); + float minutes = float.Parse(parts[1]); + float seconds = float.Parse(parts[2]); + + return hours * 3600 + minutes * 60 + seconds; + } + + public static string FormatTime(float totalSeconds) + { + int hours = (int)(totalSeconds / 3600); + int minutes = (int)((totalSeconds % 3600) / 60); + int seconds = (int)(totalSeconds % 60); + return $"{hours:00}:{minutes:00}:{seconds:00}"; + } + } +} diff --git a/unity-client/Assets/Scripts/Core/TimeUtils.cs.meta b/unity-client/Assets/Scripts/Core/TimeUtils.cs.meta new file mode 100644 index 0000000..4777bff --- /dev/null +++ b/unity-client/Assets/Scripts/Core/TimeUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f600001000000000000004 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/Data.meta b/unity-client/Assets/Scripts/Data.meta new file mode 100644 index 0000000..215c8d1 --- /dev/null +++ b/unity-client/Assets/Scripts/Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1b2c3d4e5f600001000000000000004 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/Data/ScenarioData.cs b/unity-client/Assets/Scripts/Data/ScenarioData.cs new file mode 100644 index 0000000..e283ab0 --- /dev/null +++ b/unity-client/Assets/Scripts/Data/ScenarioData.cs @@ -0,0 +1,75 @@ +using System.Xml.Serialization; +using System.Collections.Generic; + +namespace DisasterSimulator.Data +{ + [XmlRoot("scenario")] + public class Scenario + { + [XmlElement("name")] + public string Name { get; set; } + + [XmlElement("ngoCount")] + public int NgoCount { get; set; } + + [XmlElement("duration")] + public long Duration { get; set; } + + [XmlElement("hoursInDay")] + public float HoursInDay { get; set; } + + [XmlElement("mode")] + public string Mode { get; set; } + + [XmlElement("ngo")] + public List Ngos { get; set; } + + [XmlElement("tag")] + public List Tags { get; set; } + + [XmlElement("event")] + public List Events { get; set; } + + [XmlElement("library")] + public List Library { get; set; } + } + + public class NGO + { + [XmlElement("name")] + public string Name { get; set; } + + [XmlElement("passkey")] + public string Passkey { get; set; } + } + + public class Event + { + [XmlElement("recipient")] + public string Recipient { get; set; } + + [XmlElement("subject")] + public string Subject { get; set; } + + [XmlElement("time")] + public string TimeString { get; set; } + + [XmlElement("type")] + public string Type { get; set; } + + [XmlElement("location")] + public string Location { get; set; } + } + + public class LibraryItem + { + [XmlElement("subject")] + public string Subject { get; set; } + + [XmlElement("type")] + public string Type { get; set; } + + [XmlElement("location")] + public string Location { get; set; } + } +} diff --git a/unity-client/Assets/Scripts/Data/ScenarioData.cs.meta b/unity-client/Assets/Scripts/Data/ScenarioData.cs.meta new file mode 100644 index 0000000..d40d5db --- /dev/null +++ b/unity-client/Assets/Scripts/Data/ScenarioData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f600001000000000000005 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/UI.meta b/unity-client/Assets/Scripts/UI.meta new file mode 100644 index 0000000..9f53aa6 --- /dev/null +++ b/unity-client/Assets/Scripts/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1b2c3d4e5f600001000000000000005 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/UI/EventPanel.cs b/unity-client/Assets/Scripts/UI/EventPanel.cs new file mode 100644 index 0000000..d87f755 --- /dev/null +++ b/unity-client/Assets/Scripts/UI/EventPanel.cs @@ -0,0 +1,67 @@ +using UnityEngine; +using UnityEngine.UI; +using DisasterSimulator.Data; +using DisasterSimulator.Core; + +namespace DisasterSimulator.UI +{ + public class EventPanel : MonoBehaviour + { + public Text subjectText; + public Text locationText; + public Text recipientText; + public Button respondButton; + public Button ignoreButton; + + private Event currentEvent; + + public void Setup(Event evt) + { + currentEvent = evt; + if (subjectText != null) subjectText.text = evt.Subject; + if (locationText != null) locationText.text = evt.Location; + if (recipientText != null) recipientText.text = evt.Recipient; + + if (respondButton != null) + { + respondButton.onClick.RemoveAllListeners(); + respondButton.onClick.AddListener(OnRespond); + } + + if (ignoreButton != null) + { + ignoreButton.onClick.RemoveAllListeners(); + ignoreButton.onClick.AddListener(OnIgnore); + } + } + + void OnRespond() + { + // Simple logic: Spend money, gain reputation + if (GameManager.Instance != null && GameManager.Instance.ResourceManager != null) + { + if (GameManager.Instance.ResourceManager.SpendBudget(100)) + { + GameManager.Instance.ResourceManager.AddReputation(10); + Debug.Log("Responded to event!"); + Destroy(gameObject); + } + else + { + Debug.Log("Not enough budget!"); + // Maybe show some UI feedback here + } + } + } + + void OnIgnore() + { + if (GameManager.Instance != null && GameManager.Instance.ResourceManager != null) + { + GameManager.Instance.ResourceManager.LoseReputation(5); + Debug.Log("Ignored event."); + } + Destroy(gameObject); + } + } +} diff --git a/unity-client/Assets/Scripts/UI/EventPanel.cs.meta b/unity-client/Assets/Scripts/UI/EventPanel.cs.meta new file mode 100644 index 0000000..65827da --- /dev/null +++ b/unity-client/Assets/Scripts/UI/EventPanel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f600001000000000000007 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/Assets/Scripts/UI/UIManager.cs b/unity-client/Assets/Scripts/UI/UIManager.cs new file mode 100644 index 0000000..fa5bf17 --- /dev/null +++ b/unity-client/Assets/Scripts/UI/UIManager.cs @@ -0,0 +1,47 @@ +using UnityEngine; +using UnityEngine.UI; +using DisasterSimulator.Data; +using DisasterSimulator.Core; + +namespace DisasterSimulator.UI +{ + public class UIManager : MonoBehaviour + { + [Header("HUD")] + public Text timeText; + public Text budgetText; + public Text reputationText; + + [Header("Popups")] + public GameObject eventPanelPrefab; // Assign a prefab with EventPanel script + public Transform popupContainer; + + public void UpdateTime(string timeString) + { + if (timeText != null) timeText.text = timeString; + } + + public void UpdateBudget(float budget) + { + if (budgetText != null) budgetText.text = $"Budget: ${budget}"; + } + + public void UpdateReputation(float reputation) + { + if (reputationText != null) reputationText.text = $"Reputation: {reputation:F1}%"; + } + + public void ShowEventPopup(Event evt) + { + if (eventPanelPrefab != null && popupContainer != null) + { + GameObject panelObj = Instantiate(eventPanelPrefab, popupContainer); + EventPanel panel = panelObj.GetComponent(); + if (panel != null) + { + panel.Setup(evt); + } + } + } + } +} diff --git a/unity-client/Assets/Scripts/UI/UIManager.cs.meta b/unity-client/Assets/Scripts/UI/UIManager.cs.meta new file mode 100644 index 0000000..b41ec3f --- /dev/null +++ b/unity-client/Assets/Scripts/UI/UIManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f600001000000000000006 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/unity-client/ProjectSettings/ProjectVersion.txt b/unity-client/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..0d0c7eb --- /dev/null +++ b/unity-client/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 2021.3.16f1 +m_EditorVersionWithRevision: 2021.3.16f1 (4016570e4843) diff --git a/unity-client/README.md b/unity-client/README.md new file mode 100644 index 0000000..403bf24 --- /dev/null +++ b/unity-client/README.md @@ -0,0 +1,52 @@ +# Disaster Simulator - Unity Client + +This directory contains a complete Unity project for the Disaster Simulator. This implementation converts the web-based simulator into a more game-like experience where you manage resources and respond to events. + +## Prerequisites + +- Unity 2021.3 LTS or newer. + +## Getting Started + +1. **Open the Project** + - Open Unity Hub. + - Click "Open" and select the `unity-client` folder. + - Unity will import the assets (this may take a few minutes). + +2. **Open the Main Scene** + - In the Project window, navigate to `Assets/Scenes`. + - Double-click `MainScene` to open it. + +3. **Run the Simulation** + - Press Play. + - The simulation logic will run, and the time will update. + - Event popups will appear at the scheduled times. + +## Troubleshooting & Customization + +The provided `MainScene` is a starter template. You may notice: +- **Event Popups look blank:** The `EventPanel` object (under `Canvas`) is a placeholder. You need to customize its visual appearance: + - Select the `EventPanel` object in the Hierarchy (it might be disabled/greyed out). Enable it temporarily to edit. + - Add UI Text elements as children for the **Subject**, **Location**, and **Recipient**. + - Add UI Button elements as children for **Respond** and **Ignore**. + - Drag these new UI elements into the corresponding fields in the `EventPanel` script component in the Inspector. + - Once customized, disable the `EventPanel` object again (the script uses it as a template to spawn copies). + +- **Buttons not clicking:** If the UI buttons are unresponsive, ensure there is an **EventSystem** in the scene. + - If missing: Right-click in the Hierarchy window -> **UI** -> **Event System**. + +- **Scenario Data:** The project is set up to load `scenario.xml`. Ensure you have a valid `scenario.xml` file assigned to the `SimulationManager` component in the Inspector. If it's missing: + - Import your `scenario.xml` into `Assets/Resources` (rename it to `.xml` extension if needed). + - Drag it into the `Scenario File` field of the `SimulationManager`. + +## Project Structure + +- `Assets/Scripts/Data`: Data classes for XML parsing. +- `Assets/Scripts/Core`: Game logic (GameManager, SimulationManager, ResourceManager). +- `Assets/Scripts/UI`: UI management scripts. +- `Assets/Scenes`: Contains the `MainScene`. + +## Game Logic + +- **Budget:** You start with a fixed budget. Responding to events costs money. +- **Reputation:** Represents public trust. Ignoring events lowers reputation. Responding increases it.