├── Assets
├── Scripts
│ ├── ECS
│ │ ├── Components
│ │ │ ├── VoxelData.cs
│ │ │ ├── MLAgentSetup.cs.meta
│ │ │ ├── NPCAgent.cs.meta
│ │ │ ├── NPCComponent.cs.meta
│ │ │ ├── VoxelData.cs.meta
│ │ │ ├── MLAgentComponent.cs.meta
│ │ │ ├── ResourceComponent.cs.meta
│ │ │ ├── TimeComponent.cs.meta
│ │ │ ├── TerrainDataComponent.cs.meta
│ │ │ ├── TimeComponent.cs
│ │ │ ├── MLAgentComponent.cs
│ │ │ ├── MLAgentSetup.cs
│ │ │ ├── NPCComponent.cs
│ │ │ ├── NPCAgent.cs
│ │ │ ├── ResourceComponent.cs
│ │ │ └── TerrainDataComponent.cs
│ │ ├── Core
│ │ │ ├── Entity.cs.meta
│ │ │ ├── ComponentBase.cs.meta
│ │ │ ├── SystemBase.cs.meta
│ │ │ ├── WorldManager.cs.meta
│ │ │ ├── Messaging
│ │ │ │ ├── Message.cs.meta
│ │ │ │ ├── MessageBus.cs.meta
│ │ │ │ ├── SystemMessages.cs.meta
│ │ │ │ ├── Message.cs
│ │ │ │ ├── SystemMessages.cs
│ │ │ │ └── MessageBus.cs
│ │ │ ├── RequireWorldManager.cs.meta
│ │ │ ├── Messaging.meta
│ │ │ ├── RequireWorldManager.cs
│ │ │ ├── ComponentBase.cs
│ │ │ ├── Entity.cs
│ │ │ ├── SystemBase.cs
│ │ │ └── WorldManager.cs
│ │ ├── Systems
│ │ │ ├── NPCSystem.cs.meta
│ │ │ ├── TimeSystem.cs.meta
│ │ │ ├── MLAgentSystem.cs.meta
│ │ │ ├── ResourceSystem.cs.meta
│ │ │ ├── SpawnerSystem.cs.meta
│ │ │ ├── TerrainSystem.cs.meta
│ │ │ ├── MLAgentSpawnerSystem.cs.meta
│ │ │ ├── MessageDebugSystem.cs.meta
│ │ │ ├── MessageDebugSystem.cs
│ │ │ ├── TimeSystem.cs
│ │ │ ├── MLAgentSpawnerSystem.cs
│ │ │ ├── SpawnerSystem.cs
│ │ │ ├── MLAgentSystem.cs
│ │ │ ├── TerrainSystem.cs
│ │ │ └── ResourceSystem.cs
│ │ ├── Core.meta
│ │ ├── README_ML_AGENTS.md.meta
│ │ ├── Components.meta
│ │ ├── Systems.meta
│ │ └── README_ML_AGENTS.md
│ └── ECS.meta
├── Scenes
│ └── World.unity.meta
├── Scenes.meta
├── Scripts.meta
├── Shaders.meta
├── Settings.meta
├── Settings
│ ├── PC_RPAsset.asset.meta
│ ├── Mobile_RPAsset.asset.meta
│ ├── Mobile_Renderer.asset.meta
│ ├── PC_Renderer.asset.meta
│ ├── SampleSceneProfile.asset.meta
│ ├── DefaultVolumeProfile.asset.meta
│ ├── UniversalRenderPipelineGlobalSettings.asset.meta
│ ├── Mobile_Renderer.asset
│ ├── PC_Renderer.asset
│ ├── SampleSceneProfile.asset
│ ├── Mobile_RPAsset.asset
│ └── PC_RPAsset.asset
├── Shaders
│ ├── TerrainShader.shader.meta
│ └── TerrainShader.shader
└── InputSystem_Actions.inputactions.meta
├── .vscode
├── extensions.json
├── launch.json
└── settings.json
├── ProjectSettings
├── ProjectVersion.txt
├── ClusterInputManager.asset
├── PresetManager.asset
├── MultiplayerManager.asset
├── XRSettings.asset
├── VersionControlSettings.asset
├── TimeManager.asset
├── VFXManager.asset
├── EditorBuildSettings.asset
├── URPProjectSettings.asset
├── AudioManager.asset
├── ShaderGraphSettings.asset
├── TagManager.asset
├── UnityConnectSettings.asset
├── PackageManagerSettings.asset
├── MemorySettings.asset
├── DynamicsManager.asset
├── EditorSettings.asset
├── NavMeshAreas.asset
├── Physics2DSettings.asset
├── GraphicsSettings.asset
├── SceneTemplateSettings.json
├── QualitySettings.asset
└── InputManager.asset
├── .gitignore
├── Packages
├── manifest.json
└── packages-lock.json
└── README.md
/Assets/Scripts/ECS/Components/VoxelData.cs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/Entity.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 38cfc7e77ae193046b27cb93451b10f8
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/ComponentBase.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 714592cb460839745b195cccb855b508
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/SystemBase.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 50fe21552d71ba1469adc03f23d2cb60
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/WorldManager.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c684d5d82cf5cda469deed514c525c0a
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/NPCSystem.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d71a32563da5a324c9bc899c570a652c
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/TimeSystem.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 35faaabc989c9384f86cc12591c7e75a
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/MLAgentSetup.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6ed166892da44dc48b1d77849df3d24a
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/NPCAgent.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d2f04d7d017cd3047a6726bc880bc964
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/NPCComponent.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 035a0ebf89169c543ac5aa8f025fc42a
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/VoxelData.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eca57532df46acf419054fe13f128f04
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/Messaging/Message.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 14d08d27e48aecc40bdc3ece8131ff69
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/MLAgentSystem.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eef3b4e0151effa4d9ac5439eb1d2db3
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/ResourceSystem.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2fe7c5753bc41474a82880f3439cc202
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/SpawnerSystem.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a6c0f16a46dfb5247b1329cef346ce3a
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/TerrainSystem.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 23c3850355d174f4cb7f49307a377a45
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "visualstudiotoolsforunity.vstuc"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/MLAgentComponent.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 51076000c73acf2418a832a258ed74e7
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/ResourceComponent.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7e04a63a364ca844797198e95a85b8eb
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/TimeComponent.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 86c732a4c08e88a43af517c553158672
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/Messaging/MessageBus.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4c8810c78e0b91943a20379e512aabf9
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/RequireWorldManager.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 024bf044087187e4fa0cc81759c46592
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/MLAgentSpawnerSystem.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 746ce3212a6da6d4481b77f85aebd28e
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/MessageDebugSystem.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a2d50ad3dc8ac42419ee0f6105bbeaaa
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/TerrainDataComponent.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 76daffec0d2dd6746a6752bb8623ed22
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/Messaging/SystemMessages.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ad72f4a6dc3e6b1439b08bf1ad57268b
--------------------------------------------------------------------------------
/ProjectSettings/ProjectVersion.txt:
--------------------------------------------------------------------------------
1 | m_EditorVersion: 6000.0.46f1
2 | m_EditorVersionWithRevision: 6000.0.46f1 (fb93bc360d3a)
3 |
--------------------------------------------------------------------------------
/ProjectSettings/ClusterInputManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!236 &1
4 | ClusterInputManager:
5 | m_ObjectHideFlags: 0
6 | m_Inputs: []
7 |
--------------------------------------------------------------------------------
/Assets/Scenes/World.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 99c9720ab356a0642a771bea13969a05
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/ProjectSettings/PresetManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1386491679 &1
4 | PresetManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_DefaultPresets: {}
8 |
--------------------------------------------------------------------------------
/Assets/Scenes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9c53962885c2c4f449125a979d6ad240
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scripts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 927d85d6266b91246a8f1265b5935307
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Shaders.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fe574ccd28e0e974582da9a7ca1a7b2e
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 24c3b295274b5b344a10d0f4546bfeff
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Settings.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 709f11a7f3c4041caa4ef136ea32d874
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/ProjectSettings/MultiplayerManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!655991488 &1
4 | MultiplayerManager:
5 | m_ObjectHideFlags: 0
6 | m_EnableMultiplayerRoles: 0
7 | m_StrippingTypes: {}
8 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8ef790e6d0e1c044ea8f67c5e09a60f5
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/README_ML_AGENTS.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4f236b36de2b9134087a6572d4b1a428
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1e593c564fb20194e83898f7bcb502a0
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3578cecffea0a8342874f1f463ae795e
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/ProjectSettings/XRSettings.asset:
--------------------------------------------------------------------------------
1 | {
2 | "m_SettingKeys": [
3 | "VR Device Disabled",
4 | "VR Device User Alert"
5 | ],
6 | "m_SettingValues": [
7 | "False",
8 | "False"
9 | ]
10 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Attach to Unity",
6 | "type": "vstuc",
7 | "request": "attach"
8 | }
9 | ]
10 | }
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/Messaging.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 63779d4d3c1a97c4ba8df21a5560caff
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Settings/PC_RPAsset.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4b83569d67af61e458304325a23e5dfd
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Settings/Mobile_RPAsset.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5e6cbd92db86f4b18aec3ed561671858
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Settings/Mobile_Renderer.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 65bc7dbf4170f435aa868c779acfb082
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Settings/PC_Renderer.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f288ae1f4751b564a96ac7587541f7a2
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Settings/SampleSceneProfile.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 10fc4df2da32a41aaa32d77bc913491c
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 0
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Settings/DefaultVolumeProfile.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ab09877e2e707104187f6f83e2f62510
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/ProjectSettings/VersionControlSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!890905787 &1
4 | VersionControlSettings:
5 | m_ObjectHideFlags: 0
6 | m_Mode: Visible Meta Files
7 | m_CollabEditorSettings:
8 | inProgressEnabled: 1
9 |
--------------------------------------------------------------------------------
/ProjectSettings/TimeManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!5 &1
4 | TimeManager:
5 | m_ObjectHideFlags: 0
6 | Fixed Timestep: 0.02
7 | Maximum Allowed Timestep: 0.33333334
8 | m_TimeScale: 1
9 | Maximum Particle Timestep: 0.03
10 |
--------------------------------------------------------------------------------
/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 18dc0cd2c080841dea60987a38ce93fa
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Shaders/TerrainShader.shader.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2d34ed368b71d3d4986cb902d711415e
3 | ShaderImporter:
4 | externalObjects: {}
5 | defaultTextures: []
6 | nonModifiableTextures: []
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/ProjectSettings/VFXManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!937362698 &1
4 | VFXManager:
5 | m_ObjectHideFlags: 0
6 | m_IndirectShader: {fileID: 0}
7 | m_CopyBufferShader: {fileID: 0}
8 | m_SortShader: {fileID: 0}
9 | m_StripUpdateShader: {fileID: 0}
10 | m_RenderPipeSettingsPath:
11 | m_FixedTimeStep: 0.016666668
12 | m_MaxDeltaTime: 0.05
13 |
--------------------------------------------------------------------------------
/Assets/InputSystem_Actions.inputactions.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 052faaac586de48259a63d0c4782560b
3 | ScriptedImporter:
4 | internalIDToNameTable: []
5 | externalObjects: {}
6 | serializedVersion: 2
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 | script: {fileID: 11500000, guid: 8404be70184654265930450def6a9037, type: 3}
11 | generateWrapperCode: 0
12 | wrapperCodePath:
13 | wrapperClassName:
14 | wrapperCodeNamespace:
15 |
--------------------------------------------------------------------------------
/ProjectSettings/EditorBuildSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1045 &1
4 | EditorBuildSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Scenes:
8 | - enabled: 1
9 | path: Assets/Scenes/World.unity
10 | guid: 99c9720ab356a0642a771bea13969a05
11 | m_configObjects:
12 | com.unity.input.settings.actions: {fileID: -944628639613478452, guid: 052faaac586de48259a63d0c4782560b, type: 3}
13 | m_UseUCBPForAssetBundles: 0
14 |
--------------------------------------------------------------------------------
/ProjectSettings/URPProjectSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &1
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 61
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3}
13 | m_Name:
14 | m_EditorClassIdentifier:
15 | m_LastMaterialVersion: 9
16 |
--------------------------------------------------------------------------------
/ProjectSettings/AudioManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!11 &1
4 | AudioManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Volume: 1
8 | Rolloff Scale: 1
9 | Doppler Factor: 1
10 | Default Speaker Mode: 2
11 | m_SampleRate: 0
12 | m_DSPBufferSize: 1024
13 | m_VirtualVoiceCount: 512
14 | m_RealVoiceCount: 32
15 | m_SpatializerPlugin:
16 | m_AmbisonicDecoderPlugin:
17 | m_DisableAudio: 0
18 | m_VirtualizeEffects: 1
19 | m_RequestedDSPBufferSize: 0
20 |
--------------------------------------------------------------------------------
/ProjectSettings/ShaderGraphSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &1
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 61
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: de02f9e1d18f588468e474319d09a723, type: 3}
13 | m_Name:
14 | m_EditorClassIdentifier:
15 | shaderVariantLimit: 128
16 | customInterpolatorErrorThreshold: 32
17 | customInterpolatorWarningThreshold: 16
18 | customHeatmapValues: {fileID: 0}
19 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/TimeComponent.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 |
4 | namespace ECS.Components
5 | {
6 | public class TimeComponent : ComponentBase
7 | {
8 | public float CurrentTime { get; private set; }
9 | public int CurrentDay { get; private set; }
10 | public DayPeriod CurrentPeriod { get; private set; }
11 |
12 | public enum DayPeriod
13 | {
14 | Dawn,
15 | Day,
16 | Dusk,
17 | Night
18 | }
19 |
20 | public void UpdateTime(float newTime, int day, DayPeriod period)
21 | {
22 | CurrentTime = newTime;
23 | CurrentDay = day;
24 | CurrentPeriod = period;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/RequireWorldManager.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace ECS.Core
4 | {
5 | ///
6 | /// Add this attribute to any MonoBehaviour that requires a WorldManager in the scene.
7 | /// It will automatically create one if none exists.
8 | ///
9 | public class RequireWorldManager : MonoBehaviour
10 | {
11 | protected virtual void Awake()
12 | {
13 | var worldManager = Object.FindFirstObjectByType();
14 | if (worldManager == null)
15 | {
16 | var go = new GameObject("World Manager");
17 | worldManager = go.AddComponent();
18 | Debug.Log("Created WorldManager automatically");
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/Messaging/Message.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System;
3 |
4 | namespace ECS.Core.Messaging
5 | {
6 | public class Message
7 | {
8 | // Unique ID for message tracking
9 | public readonly Guid Id = Guid.NewGuid();
10 |
11 | // Timestamp when message was created
12 | public readonly float Timestamp = Time.time;
13 |
14 | // Source of the message (can be null)
15 | public readonly Entity Source;
16 |
17 | // Priority of the message
18 | public MessagePriority Priority { get; set; } = MessagePriority.Normal;
19 |
20 | public Message(Entity source = null)
21 | {
22 | Source = source;
23 | }
24 | }
25 |
26 | // Priority levels for message processing
27 | public enum MessagePriority
28 | {
29 | Low = 0,
30 | Normal = 1,
31 | High = 2,
32 | Critical = 3
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ProjectSettings/TagManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!78 &1
4 | TagManager:
5 | serializedVersion: 2
6 | tags: []
7 | layers:
8 | - Default
9 | - TransparentFX
10 | - Ignore Raycast
11 | -
12 | - Water
13 | - UI
14 | -
15 | -
16 | -
17 | -
18 | -
19 | -
20 | -
21 | -
22 | -
23 | -
24 | -
25 | -
26 | -
27 | -
28 | -
29 | -
30 | -
31 | -
32 | -
33 | -
34 | -
35 | -
36 | -
37 | -
38 | -
39 | -
40 | m_SortingLayers:
41 | - name: Default
42 | uniqueID: 0
43 | locked: 0
44 | m_RenderingLayers:
45 | - Default
46 | - Light Layer 1
47 | - Light Layer 2
48 | - Light Layer 3
49 | - Light Layer 4
50 | - Light Layer 5
51 | - Light Layer 6
52 | - Light Layer 7
53 | -
54 | -
55 | -
56 | -
57 | -
58 | -
59 | -
60 | -
61 | -
62 | -
63 | -
64 | -
65 | -
66 | -
67 | -
68 | -
69 | -
70 | -
71 | -
72 | -
73 | -
74 | -
75 | -
76 | -
77 |
--------------------------------------------------------------------------------
/ProjectSettings/UnityConnectSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!310 &1
4 | UnityConnectSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 1
7 | m_Enabled: 0
8 | m_TestMode: 0
9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events
11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com
12 | m_DashboardUrl: https://dashboard.unity3d.com
13 | m_TestInitMode: 0
14 | CrashReportingSettings:
15 | m_EventUrl: https://perf-events.cloud.unity3d.com
16 | m_Enabled: 0
17 | m_LogBufferSize: 10
18 | m_CaptureEditorExceptions: 1
19 | UnityPurchasingSettings:
20 | m_Enabled: 0
21 | m_TestMode: 0
22 | UnityAnalyticsSettings:
23 | m_Enabled: 0
24 | m_TestMode: 0
25 | m_InitializeOnStartup: 1
26 | m_PackageRequiringCoreStatsPresent: 0
27 | UnityAdsSettings:
28 | m_Enabled: 0
29 | m_InitializeOnStartup: 1
30 | m_TestMode: 0
31 | m_IosGameId:
32 | m_AndroidGameId:
33 | m_GameIds: {}
34 | m_GameId:
35 | PerformanceReportingSettings:
36 | m_Enabled: 0
37 |
--------------------------------------------------------------------------------
/ProjectSettings/PackageManagerSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &1
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 61
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}
13 | m_Name:
14 | m_EditorClassIdentifier:
15 | m_EnablePreviewPackages: 0
16 | m_EnablePackageDependencies: 0
17 | m_AdvancedSettingsExpanded: 1
18 | m_ScopedRegistriesSettingsExpanded: 1
19 | oneTimeWarningShown: 0
20 | m_Registries:
21 | - m_Id: main
22 | m_Name:
23 | m_Url: https://packages.unity.com
24 | m_Scopes: []
25 | m_IsDefault: 1
26 | m_Capabilities: 7
27 | m_UserSelectedRegistryName:
28 | m_UserAddingNewScopedRegistry: 0
29 | m_RegistryInfoDraft:
30 | m_ErrorMessage:
31 | m_Original:
32 | m_Id:
33 | m_Name:
34 | m_Url:
35 | m_Scopes: []
36 | m_IsDefault: 0
37 | m_Capabilities: 0
38 | m_Modified: 0
39 | m_Name:
40 | m_Url:
41 | m_Scopes:
42 | -
43 | m_SelectedScopeIndex: 0
44 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/MLAgentComponent.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 |
4 | namespace ECS.Components
5 | {
6 | public class MLAgentComponent : ComponentBase
7 | {
8 | // Reference to the NPC component
9 | public NPCComponent npcComponent;
10 |
11 | // Flag to determine if ML-Agent is in control
12 | public bool isActive = true;
13 |
14 | // Last decision made by the ML-Agent (0=Idle, 1=Food, 2=Water, 3=Rest, 4=Social)
15 | public int lastAction;
16 |
17 | // Reward accumulation
18 | public float accumulatedReward = 0f;
19 |
20 | protected override void Awake()
21 | {
22 | base.Awake();
23 |
24 | // Get the NPC component
25 | npcComponent = GetComponent();
26 | }
27 |
28 | public void AddReward(float reward)
29 | {
30 | accumulatedReward += reward;
31 | }
32 |
33 | public void SetReward(float reward)
34 | {
35 | accumulatedReward = reward;
36 | }
37 |
38 | public void EndEpisode()
39 | {
40 | accumulatedReward = 0f;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/ProjectSettings/MemorySettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!387306366 &1
4 | MemorySettings:
5 | m_ObjectHideFlags: 0
6 | m_EditorMemorySettings:
7 | m_MainAllocatorBlockSize: -1
8 | m_ThreadAllocatorBlockSize: -1
9 | m_MainGfxBlockSize: -1
10 | m_ThreadGfxBlockSize: -1
11 | m_CacheBlockSize: -1
12 | m_TypetreeBlockSize: -1
13 | m_ProfilerBlockSize: -1
14 | m_ProfilerEditorBlockSize: -1
15 | m_BucketAllocatorGranularity: -1
16 | m_BucketAllocatorBucketsCount: -1
17 | m_BucketAllocatorBlockSize: -1
18 | m_BucketAllocatorBlockCount: -1
19 | m_ProfilerBucketAllocatorGranularity: -1
20 | m_ProfilerBucketAllocatorBucketsCount: -1
21 | m_ProfilerBucketAllocatorBlockSize: -1
22 | m_ProfilerBucketAllocatorBlockCount: -1
23 | m_TempAllocatorSizeMain: -1
24 | m_JobTempAllocatorBlockSize: -1
25 | m_BackgroundJobTempAllocatorBlockSize: -1
26 | m_JobTempAllocatorReducedBlockSize: -1
27 | m_TempAllocatorSizeGIBakingWorker: -1
28 | m_TempAllocatorSizeNavMeshWorker: -1
29 | m_TempAllocatorSizeAudioWorker: -1
30 | m_TempAllocatorSizeCloudWorker: -1
31 | m_TempAllocatorSizeGfx: -1
32 | m_TempAllocatorSizeJobWorker: -1
33 | m_TempAllocatorSizeBackgroundWorker: -1
34 | m_TempAllocatorSizePreloadManager: -1
35 | m_PlatformMemorySettings: {}
36 |
--------------------------------------------------------------------------------
/ProjectSettings/DynamicsManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!55 &1
4 | PhysicsManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 13
7 | m_Gravity: {x: 0, y: -9.81, z: 0}
8 | m_DefaultMaterial: {fileID: 0}
9 | m_BounceThreshold: 2
10 | m_SleepThreshold: 0.005
11 | m_DefaultContactOffset: 0.01
12 | m_DefaultSolverIterations: 6
13 | m_DefaultSolverVelocityIterations: 1
14 | m_QueriesHitBackfaces: 0
15 | m_QueriesHitTriggers: 1
16 | m_EnableAdaptiveForce: 0
17 | m_ClothInterCollisionDistance: 0.1
18 | m_ClothInterCollisionStiffness: 0.2
19 | m_ContactsGeneration: 1
20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
21 | m_AutoSimulation: 1
22 | m_AutoSyncTransforms: 0
23 | m_ReuseCollisionCallbacks: 1
24 | m_ClothInterCollisionSettingsToggle: 0
25 | m_ClothGravity: {x: 0, y: -9.81, z: 0}
26 | m_ContactPairsMode: 0
27 | m_BroadphaseType: 0
28 | m_WorldBounds:
29 | m_Center: {x: 0, y: 0, z: 0}
30 | m_Extent: {x: 250, y: 250, z: 250}
31 | m_WorldSubdivisions: 8
32 | m_FrictionType: 0
33 | m_EnableEnhancedDeterminism: 0
34 | m_EnableUnifiedHeightmaps: 1
35 | m_SolverType: 0
36 | m_DefaultMaxAngularSpeed: 50
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # This .gitignore file should be placed at the root of your Unity project directory
2 | #
3 | # Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
4 | #
5 | /[Ll]ibrary/
6 | /[Tt]emp/
7 | /[Oo]bj/
8 | /[Bb]uild/
9 | /[Bb]uilds/
10 | /[Ll]ogs/
11 | /[Uu]ser[Ss]ettings/
12 |
13 | # MemoryCaptures can get excessive in size.
14 | # They also could contain extremely sensitive data
15 | /[Mm]emoryCaptures/
16 |
17 | # Recordings can get excessive in size
18 | /[Rr]ecordings/
19 |
20 | # Uncomment this line if you wish to ignore the asset store tools plugin
21 | # /[Aa]ssets/AssetStoreTools*
22 |
23 | # Autogenerated Jetbrains Rider plugin
24 | /[Aa]ssets/Plugins/Editor/JetBrains*
25 |
26 | # Visual Studio cache directory
27 | .vs/
28 |
29 | # Gradle cache directory
30 | .gradle/
31 |
32 | # Autogenerated VS/MD/Consulo solution and project files
33 | ExportedObj/
34 | .consulo/
35 | *.csproj
36 | *.unityproj
37 | *.sln
38 | *.suo
39 | *.tmp
40 | *.user
41 | *.userprefs
42 | *.pidb
43 | *.booproj
44 | *.svd
45 | *.pdb
46 | *.mdb
47 | *.opendb
48 | *.VC.db
49 |
50 | # Unity3D generated meta files
51 | *.pidb.meta
52 | *.pdb.meta
53 | *.mdb.meta
54 |
55 | # Unity3D generated file on crash reports
56 | sysinfo.txt
57 |
58 | # Builds
59 | *.apk
60 | *.aab
61 | *.unitypackage
62 | *.unitypackage.meta
63 | *.app
64 |
65 | # Crashlytics generated file
66 | crashlytics-build.properties
67 |
68 | # Packed Addressables
69 | /[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*
70 |
71 | # Temporary auto-generated Android Assets
72 | /[Aa]ssets/[Ss]treamingAssets/aa.meta
73 | /[Aa]ssets/[Ss]treamingAssets/aa/*
74 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/MessageDebugSystem.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 | using ECS.Core.Messaging;
4 |
5 | namespace ECS.Systems
6 | {
7 | ///
8 | /// Example system that demonstrates message subscription and handling
9 | ///
10 | public class MessageDebugSystem : SystemBase
11 | {
12 | protected override void Initialize()
13 | {
14 | // Subscribe to system initialization messages
15 | SubscribeToMessage(OnSystemInitialized);
16 |
17 | // Subscribe to time change messages
18 | SubscribeToMessage(OnTimeChanged);
19 |
20 | base.Initialize();
21 | }
22 |
23 | private void OnSystemInitialized(SystemInitializedMessage message)
24 | {
25 | Debug.Log($"[MessageDebugSystem] System initialized: {message.SystemName}");
26 | }
27 |
28 | private void OnTimeChanged(TimeChangedMessage message)
29 | {
30 | Debug.Log($"[MessageDebugSystem] Time period changed from {message.PreviousPeriod} to {message.NewPeriod} on day {message.CurrentDay}");
31 | }
32 |
33 | protected override void OnDestroy()
34 | {
35 | // Unsubscribe from messages (although SystemBase.OnDestroy already handles this through MessageBus.ClearSubscriptions)
36 | if (MessageBus != null)
37 | {
38 | UnsubscribeFromMessage(OnSystemInitialized);
39 | UnsubscribeFromMessage(OnTimeChanged);
40 | }
41 |
42 | base.OnDestroy();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/ProjectSettings/EditorSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!159 &1
4 | EditorSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 13
7 | m_SerializationMode: 2
8 | m_LineEndingsForNewScripts: 0
9 | m_DefaultBehaviorMode: 0
10 | m_PrefabRegularEnvironment: {fileID: 0}
11 | m_PrefabUIEnvironment: {fileID: 0}
12 | m_SpritePackerMode: 0
13 | m_SpritePackerCacheSize: 10
14 | m_SpritePackerPaddingPower: 1
15 | m_Bc7TextureCompressor: 0
16 | m_EtcTextureCompressorBehavior: 1
17 | m_EtcTextureFastCompressor: 1
18 | m_EtcTextureNormalCompressor: 2
19 | m_EtcTextureBestCompressor: 4
20 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref
21 | m_ProjectGenerationRootNamespace:
22 | m_EnableTextureStreamingInEditMode: 1
23 | m_EnableTextureStreamingInPlayMode: 1
24 | m_EnableEditorAsyncCPUTextureLoading: 0
25 | m_AsyncShaderCompilation: 1
26 | m_PrefabModeAllowAutoSave: 1
27 | m_EnterPlayModeOptionsEnabled: 1
28 | m_EnterPlayModeOptions: 0
29 | m_GameObjectNamingDigits: 1
30 | m_GameObjectNamingScheme: 0
31 | m_AssetNamingUsesSpace: 1
32 | m_InspectorUseIMGUIDefaultInspector: 0
33 | m_UseLegacyProbeSampleCount: 0
34 | m_SerializeInlineMappingsOnOneLine: 1
35 | m_DisableCookiesInLightmapper: 0
36 | m_AssetPipelineMode: 1
37 | m_RefreshImportMode: 0
38 | m_CacheServerMode: 0
39 | m_CacheServerEndpoint:
40 | m_CacheServerNamespacePrefix: default
41 | m_CacheServerEnableDownload: 1
42 | m_CacheServerEnableUpload: 1
43 | m_CacheServerEnableAuth: 0
44 | m_CacheServerEnableTls: 0
45 | m_CacheServerValidationMode: 2
46 | m_CacheServerDownloadBatchSize: 128
47 | m_EnableEnlightenBakedGI: 0
48 | m_ReferencedClipsExactNaming: 1
49 |
--------------------------------------------------------------------------------
/ProjectSettings/NavMeshAreas.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!126 &1
4 | NavMeshProjectSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | areas:
8 | - name: Walkable
9 | cost: 1
10 | - name: Not Walkable
11 | cost: 1
12 | - name: Jump
13 | cost: 2
14 | - name:
15 | cost: 1
16 | - name:
17 | cost: 1
18 | - name:
19 | cost: 1
20 | - name:
21 | cost: 1
22 | - name:
23 | cost: 1
24 | - name:
25 | cost: 1
26 | - name:
27 | cost: 1
28 | - name:
29 | cost: 1
30 | - name:
31 | cost: 1
32 | - name:
33 | cost: 1
34 | - name:
35 | cost: 1
36 | - name:
37 | cost: 1
38 | - name:
39 | cost: 1
40 | - name:
41 | cost: 1
42 | - name:
43 | cost: 1
44 | - name:
45 | cost: 1
46 | - name:
47 | cost: 1
48 | - name:
49 | cost: 1
50 | - name:
51 | cost: 1
52 | - name:
53 | cost: 1
54 | - name:
55 | cost: 1
56 | - name:
57 | cost: 1
58 | - name:
59 | cost: 1
60 | - name:
61 | cost: 1
62 | - name:
63 | cost: 1
64 | - name:
65 | cost: 1
66 | - name:
67 | cost: 1
68 | - name:
69 | cost: 1
70 | - name:
71 | cost: 1
72 | m_LastAgentTypeID: -887442657
73 | m_Settings:
74 | - serializedVersion: 2
75 | agentTypeID: 0
76 | agentRadius: 0.5
77 | agentHeight: 2
78 | agentSlope: 45
79 | agentClimb: 0.75
80 | ledgeDropHeight: 0
81 | maxJumpAcrossDistance: 0
82 | minRegionArea: 2
83 | manualCellSize: 0
84 | cellSize: 0.16666667
85 | manualTileSize: 0
86 | tileSize: 256
87 | accuratePlacement: 0
88 | debug:
89 | m_Flags: 0
90 | m_SettingNames:
91 | - Humanoid
92 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.exclude": {
3 | "**/.DS_Store": true,
4 | "**/.git": true,
5 | "**/.vs": true,
6 | "**/.gitmodules": true,
7 | "**/.vsconfig": true,
8 | "**/*.booproj": true,
9 | "**/*.pidb": true,
10 | "**/*.suo": true,
11 | "**/*.user": true,
12 | "**/*.userprefs": true,
13 | "**/*.unityproj": true,
14 | "**/*.dll": true,
15 | "**/*.exe": true,
16 | "**/*.pdf": true,
17 | "**/*.mid": true,
18 | "**/*.midi": true,
19 | "**/*.wav": true,
20 | "**/*.gif": true,
21 | "**/*.ico": true,
22 | "**/*.jpg": true,
23 | "**/*.jpeg": true,
24 | "**/*.png": true,
25 | "**/*.psd": true,
26 | "**/*.tga": true,
27 | "**/*.tif": true,
28 | "**/*.tiff": true,
29 | "**/*.3ds": true,
30 | "**/*.3DS": true,
31 | "**/*.fbx": true,
32 | "**/*.FBX": true,
33 | "**/*.lxo": true,
34 | "**/*.LXO": true,
35 | "**/*.ma": true,
36 | "**/*.MA": true,
37 | "**/*.obj": true,
38 | "**/*.OBJ": true,
39 | "**/*.asset": true,
40 | "**/*.cubemap": true,
41 | "**/*.flare": true,
42 | "**/*.mat": true,
43 | "**/*.meta": true,
44 | "**/*.prefab": true,
45 | "**/*.unity": true,
46 | "build/": true,
47 | "Build/": true,
48 | "Library/": true,
49 | "library/": true,
50 | "obj/": true,
51 | "Obj/": true,
52 | "Logs/": true,
53 | "logs/": true,
54 | "ProjectSettings/": true,
55 | "UserSettings/": true,
56 | "temp/": true,
57 | "Temp/": true
58 | },
59 | "dotnet.defaultSolution": "Unity-ECS-Starter.sln"
60 | }
--------------------------------------------------------------------------------
/Assets/Settings/Mobile_Renderer.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &11400000
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 0
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3}
13 | m_Name: Mobile_Renderer
14 | m_EditorClassIdentifier:
15 | debugShaders:
16 | debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7,
17 | type: 3}
18 | hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3}
19 | probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959,
20 | type: 3}
21 | probeVolumeResources:
22 | probeVolumeDebugShader: {fileID: 0}
23 | probeVolumeFragmentationDebugShader: {fileID: 0}
24 | probeVolumeOffsetDebugShader: {fileID: 0}
25 | probeVolumeSamplingDebugShader: {fileID: 0}
26 | probeSamplingDebugMesh: {fileID: 0}
27 | probeSamplingDebugTexture: {fileID: 0}
28 | probeVolumeBlendStatesCS: {fileID: 0}
29 | m_RendererFeatures: []
30 | m_RendererFeatureMap:
31 | m_UseNativeRenderPass: 1
32 | postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2}
33 | m_AssetVersion: 2
34 | m_OpaqueLayerMask:
35 | serializedVersion: 2
36 | m_Bits: 4294967295
37 | m_TransparentLayerMask:
38 | serializedVersion: 2
39 | m_Bits: 4294967295
40 | m_DefaultStencilState:
41 | overrideStencilState: 0
42 | stencilReference: 0
43 | stencilCompareFunction: 8
44 | passOperation: 2
45 | failOperation: 0
46 | zFailOperation: 0
47 | m_ShadowTransparentReceive: 0
48 | m_RenderingMode: 2
49 | m_DepthPrimingMode: 0
50 | m_CopyDepthMode: 0
51 | m_AccurateGbufferNormals: 0
52 | m_IntermediateTextureMode: 0
53 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/ComponentBase.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace ECS.Core
4 | {
5 | public abstract class ComponentBase : MonoBehaviour
6 | {
7 | protected WorldManager worldManager;
8 | protected Entity entity;
9 |
10 | protected virtual void Awake()
11 | {
12 | // Get or create entity component
13 | entity = GetComponent();
14 | if (entity == null)
15 | {
16 | entity = gameObject.AddComponent();
17 | Debug.Log($"[{GetType().Name}] Created Entity component");
18 | }
19 |
20 | // Find world manager
21 | worldManager = Object.FindFirstObjectByType(FindObjectsInactive.Include);
22 | if (worldManager == null)
23 | {
24 | var go = new GameObject("World Manager");
25 | worldManager = go.AddComponent();
26 | Debug.Log($"[{GetType().Name}] Created WorldManager automatically");
27 | }
28 |
29 | // Register with entity
30 | if (entity != null)
31 | {
32 | entity.RegisterComponent(this);
33 | Debug.Log($"[{GetType().Name}] Registered with Entity {entity.gameObject.name}");
34 | }
35 | else
36 | {
37 | Debug.LogError($"[{GetType().Name}] Failed to get or create Entity component");
38 | }
39 | }
40 |
41 | protected virtual void OnDestroy()
42 | {
43 | if (entity != null)
44 | {
45 | entity.UnregisterComponent(this);
46 | Debug.Log($"[{GetType().Name}] Unregistered from Entity {entity.gameObject.name}");
47 | }
48 | }
49 |
50 | public virtual void Initialize()
51 | {
52 | Debug.Log($"[{GetType().Name}] Initialized");
53 | }
54 |
55 | // Helper method to get the entity
56 | public Entity GetEntity() => entity;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/MLAgentSetup.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace ECS.Components
4 | {
5 | ///
6 | /// Helper component to set up ML-Agent components on an NPC.
7 | /// Attach this to any NPC GameObject to enable ML-Agent functionality.
8 | ///
9 | [RequireComponent(typeof(NPCComponent))]
10 | public class MLAgentSetup : MonoBehaviour
11 | {
12 | [Header("ML-Agent Configuration")]
13 | [Tooltip("Whether to use the ML-Agent for decision making")]
14 | public bool enableAgent = true;
15 |
16 | [Tooltip("Decision making interval in seconds")]
17 | public float decisionInterval = 0.5f;
18 |
19 | [Tooltip("Add randomness to decisions based on curiosity")]
20 | public bool useRandomness = true;
21 |
22 | private void Awake()
23 | {
24 | // Add required ML-Agent components
25 | SetupMLAgentComponents();
26 | }
27 |
28 | private void SetupMLAgentComponents()
29 | {
30 | // Add MLAgentComponent
31 | var mlAgentComponent = gameObject.AddComponent();
32 | mlAgentComponent.isActive = enableAgent;
33 |
34 | // Add NPCAgent
35 | var npcAgent = gameObject.AddComponent();
36 |
37 | // Configure NPCAgent
38 | if (npcAgent != null)
39 | {
40 | // Set decision interval using reflection since it's private
41 | var field = npcAgent.GetType().GetField("decisionInterval",
42 | System.Reflection.BindingFlags.Instance |
43 | System.Reflection.BindingFlags.NonPublic);
44 |
45 | if (field != null)
46 | {
47 | field.SetValue(npcAgent, decisionInterval);
48 | }
49 | }
50 |
51 | Debug.Log($"[MLAgentSetup] ML-Agent components set up for {gameObject.name}");
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Packages/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "com.unity.ai.navigation": "2.0.6",
4 | "com.unity.collab-proxy": "2.7.1",
5 | "com.unity.ide.rider": "3.0.35",
6 | "com.unity.ide.visualstudio": "2.0.23",
7 | "com.unity.inputsystem": "1.14.0",
8 | "com.unity.multiplayer.center": "1.0.0",
9 | "com.unity.render-pipelines.universal": "17.0.4",
10 | "com.unity.test-framework": "1.5.1",
11 | "com.unity.timeline": "1.8.7",
12 | "com.unity.ugui": "2.0.0",
13 | "com.unity.visualscripting": "1.9.6",
14 | "com.unity.modules.accessibility": "1.0.0",
15 | "com.unity.modules.ai": "1.0.0",
16 | "com.unity.modules.androidjni": "1.0.0",
17 | "com.unity.modules.animation": "1.0.0",
18 | "com.unity.modules.assetbundle": "1.0.0",
19 | "com.unity.modules.audio": "1.0.0",
20 | "com.unity.modules.cloth": "1.0.0",
21 | "com.unity.modules.director": "1.0.0",
22 | "com.unity.modules.imageconversion": "1.0.0",
23 | "com.unity.modules.imgui": "1.0.0",
24 | "com.unity.modules.jsonserialize": "1.0.0",
25 | "com.unity.modules.particlesystem": "1.0.0",
26 | "com.unity.modules.physics": "1.0.0",
27 | "com.unity.modules.physics2d": "1.0.0",
28 | "com.unity.modules.screencapture": "1.0.0",
29 | "com.unity.modules.terrain": "1.0.0",
30 | "com.unity.modules.terrainphysics": "1.0.0",
31 | "com.unity.modules.tilemap": "1.0.0",
32 | "com.unity.modules.ui": "1.0.0",
33 | "com.unity.modules.uielements": "1.0.0",
34 | "com.unity.modules.umbra": "1.0.0",
35 | "com.unity.modules.unityanalytics": "1.0.0",
36 | "com.unity.modules.unitywebrequest": "1.0.0",
37 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0",
38 | "com.unity.modules.unitywebrequestaudio": "1.0.0",
39 | "com.unity.modules.unitywebrequesttexture": "1.0.0",
40 | "com.unity.modules.unitywebrequestwww": "1.0.0",
41 | "com.unity.modules.vehicles": "1.0.0",
42 | "com.unity.modules.video": "1.0.0",
43 | "com.unity.modules.vr": "1.0.0",
44 | "com.unity.modules.wind": "1.0.0",
45 | "com.unity.modules.xr": "1.0.0"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/ProjectSettings/Physics2DSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!19 &1
4 | Physics2DSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 4
7 | m_Gravity: {x: 0, y: -9.81}
8 | m_DefaultMaterial: {fileID: 0}
9 | m_VelocityIterations: 8
10 | m_PositionIterations: 3
11 | m_VelocityThreshold: 1
12 | m_MaxLinearCorrection: 0.2
13 | m_MaxAngularCorrection: 8
14 | m_MaxTranslationSpeed: 100
15 | m_MaxRotationSpeed: 360
16 | m_BaumgarteScale: 0.2
17 | m_BaumgarteTimeOfImpactScale: 0.75
18 | m_TimeToSleep: 0.5
19 | m_LinearSleepTolerance: 0.01
20 | m_AngularSleepTolerance: 2
21 | m_DefaultContactOffset: 0.01
22 | m_JobOptions:
23 | serializedVersion: 2
24 | useMultithreading: 0
25 | useConsistencySorting: 0
26 | m_InterpolationPosesPerJob: 100
27 | m_NewContactsPerJob: 30
28 | m_CollideContactsPerJob: 100
29 | m_ClearFlagsPerJob: 200
30 | m_ClearBodyForcesPerJob: 200
31 | m_SyncDiscreteFixturesPerJob: 50
32 | m_SyncContinuousFixturesPerJob: 50
33 | m_FindNearestContactsPerJob: 100
34 | m_UpdateTriggerContactsPerJob: 100
35 | m_IslandSolverCostThreshold: 100
36 | m_IslandSolverBodyCostScale: 1
37 | m_IslandSolverContactCostScale: 10
38 | m_IslandSolverJointCostScale: 10
39 | m_IslandSolverBodiesPerJob: 50
40 | m_IslandSolverContactsPerJob: 50
41 | m_AutoSimulation: 1
42 | m_QueriesHitTriggers: 1
43 | m_QueriesStartInColliders: 1
44 | m_CallbacksOnDisable: 1
45 | m_ReuseCollisionCallbacks: 0
46 | m_AutoSyncTransforms: 0
47 | m_AlwaysShowColliders: 0
48 | m_ShowColliderSleep: 1
49 | m_ShowColliderContacts: 0
50 | m_ShowColliderAABB: 0
51 | m_ContactArrowScale: 0.2
52 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412}
53 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432}
54 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745}
55 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804}
56 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
57 |
--------------------------------------------------------------------------------
/ProjectSettings/GraphicsSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!30 &1
4 | GraphicsSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 16
7 | m_Deferred:
8 | m_Mode: 1
9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
10 | m_DeferredReflections:
11 | m_Mode: 1
12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}
13 | m_ScreenSpaceShadows:
14 | m_Mode: 1
15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}
16 | m_DepthNormals:
17 | m_Mode: 1
18 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}
19 | m_MotionVectors:
20 | m_Mode: 1
21 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}
22 | m_LightHalo:
23 | m_Mode: 1
24 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}
25 | m_LensFlare:
26 | m_Mode: 1
27 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
28 | m_VideoShadersIncludeMode: 2
29 | m_AlwaysIncludedShaders:
30 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
31 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
32 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}
33 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
34 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
35 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
36 | - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0}
37 | m_PreloadedShaders: []
38 | m_PreloadShadersBatchTimeLimit: -1
39 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
40 | type: 0}
41 | m_CustomRenderPipeline: {fileID: 11400000, guid: 4b83569d67af61e458304325a23e5dfd,
42 | type: 2}
43 | m_TransparencySortMode: 0
44 | m_TransparencySortAxis: {x: 0, y: 0, z: 1}
45 | m_DefaultRenderingPath: 1
46 | m_DefaultMobileRenderingPath: 1
47 | m_TierSettings: []
48 | m_LightmapStripping: 0
49 | m_FogStripping: 0
50 | m_InstancingStripping: 0
51 | m_BrgStripping: 0
52 | m_LightmapKeepPlain: 1
53 | m_LightmapKeepDirCombined: 1
54 | m_LightmapKeepDynamicPlain: 1
55 | m_LightmapKeepDynamicDirCombined: 1
56 | m_LightmapKeepShadowMask: 1
57 | m_LightmapKeepSubtractive: 1
58 | m_FogKeepLinear: 1
59 | m_FogKeepExp: 1
60 | m_FogKeepExp2: 1
61 | m_AlbedoSwatchInfos: []
62 | m_RenderPipelineGlobalSettingsMap:
63 | UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 18dc0cd2c080841dea60987a38ce93fa,
64 | type: 2}
65 | m_LightsUseLinearIntensity: 1
66 | m_LightsUseColorTemperature: 1
67 | m_LogWhenShaderIsCompiled: 0
68 | m_LightProbeOutsideHullStrategy: 0
69 | m_CameraRelativeLightCulling: 0
70 | m_CameraRelativeShadowCulling: 0
71 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/NPCComponent.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 |
4 | namespace ECS.Components
5 | {
6 | public class NPCComponent : ComponentBase
7 | {
8 | [System.Serializable]
9 | public class Needs
10 | {
11 | public float hunger;
12 | public float thirst;
13 | public float energy;
14 | public float social;
15 |
16 | public void Update(float deltaTime)
17 | {
18 | // Needs naturally increase over time
19 | hunger += deltaTime * 0.1f;
20 | thirst += deltaTime * 0.15f;
21 | energy += deltaTime * 0.05f;
22 | social += deltaTime * 0.08f;
23 |
24 | // Clamp values
25 | hunger = Mathf.Clamp01(hunger);
26 | thirst = Mathf.Clamp01(thirst);
27 | energy = Mathf.Clamp01(energy);
28 | social = Mathf.Clamp01(social);
29 | }
30 | }
31 |
32 | [System.Serializable]
33 | public class Personality
34 | {
35 | public float sociability = 0.5f; // How much they seek social interaction
36 | public float bravery = 0.5f; // Willingness to take risks
37 | public float curiosity = 0.5f; // Tendency to explore
38 | public float diligence = 0.5f; // Work ethic and task focus
39 | }
40 |
41 | public enum NPCState
42 | {
43 | Idle,
44 | Moving,
45 | Interacting,
46 | Working,
47 | Resting,
48 | Eating,
49 | Drinking,
50 | Socializing
51 | }
52 |
53 | [Header("NPC Settings")]
54 | public string npcName;
55 | public Needs needs = new Needs();
56 | public Personality personality = new Personality();
57 | public NPCState currentState = NPCState.Idle;
58 |
59 | [Header("Movement")]
60 | public float moveSpeed = 5f;
61 | public float rotationSpeed = 120f;
62 | public float interactionRange = 2f;
63 |
64 | private Vector3 targetPosition;
65 | private Transform targetEntity;
66 |
67 | public void SetTarget(Vector3 position)
68 | {
69 | targetPosition = position;
70 | targetEntity = null;
71 | currentState = NPCState.Moving;
72 | }
73 |
74 | public void SetTarget(Transform entity)
75 | {
76 | targetEntity = entity;
77 | currentState = NPCState.Moving;
78 | }
79 |
80 | public Vector3 GetTargetPosition()
81 | {
82 | return targetEntity != null ? targetEntity.position : targetPosition;
83 | }
84 |
85 | public bool HasReachedTarget()
86 | {
87 | Vector3 target = GetTargetPosition();
88 | return Vector3.Distance(transform.position, target) < 0.1f;
89 | }
90 |
91 | public void SetState(NPCState newState)
92 | {
93 | if (currentState != newState)
94 | {
95 | currentState = newState;
96 | OnStateChanged(newState);
97 | }
98 | }
99 |
100 | protected virtual void OnStateChanged(NPCState newState)
101 | {
102 | Debug.Log($"{npcName} changed state to {newState}");
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/NPCAgent.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 |
4 | namespace ECS.Components
5 | {
6 | public class NPCAgent : MonoBehaviour
7 | {
8 | private NPCComponent npcComponent;
9 | private MLAgentComponent mlAgentComponent;
10 | private WorldManager worldManager;
11 |
12 | [SerializeField] private float decisionInterval = 0.5f;
13 | private float nextDecisionTime;
14 |
15 | private void Awake()
16 | {
17 | npcComponent = GetComponent();
18 | mlAgentComponent = GetComponent();
19 | worldManager = FindObjectOfType();
20 |
21 | nextDecisionTime = Time.time + decisionInterval;
22 | }
23 |
24 | private void Update()
25 | {
26 | if (Time.time >= nextDecisionTime)
27 | {
28 | nextDecisionTime = Time.time + decisionInterval;
29 | MakeDecision();
30 | }
31 | }
32 |
33 | public void MakeDecision()
34 | {
35 | if (npcComponent == null || mlAgentComponent == null) return;
36 |
37 | // Simple heuristic based on NPC needs
38 | float highestNeed = 0f;
39 | int actionType = 0; // Default to idle
40 |
41 | if (npcComponent.needs.hunger > highestNeed)
42 | {
43 | highestNeed = npcComponent.needs.hunger;
44 | actionType = 1; // Seek food
45 | }
46 |
47 | if (npcComponent.needs.thirst > highestNeed)
48 | {
49 | highestNeed = npcComponent.needs.thirst;
50 | actionType = 2; // Seek water
51 | }
52 |
53 | if (npcComponent.needs.energy > highestNeed)
54 | {
55 | highestNeed = npcComponent.needs.energy;
56 | actionType = 3; // Seek rest
57 | }
58 |
59 | if (npcComponent.needs.social > highestNeed * npcComponent.personality.sociability)
60 | {
61 | highestNeed = npcComponent.needs.social;
62 | actionType = 4; // Seek social
63 | }
64 |
65 | // Add some randomness based on curiosity
66 | if (Random.value < npcComponent.personality.curiosity * 0.2f)
67 | {
68 | actionType = Random.Range(0, 5);
69 | }
70 |
71 | // Store the action
72 | mlAgentComponent.lastAction = actionType;
73 |
74 | // Calculate and apply rewards
75 | CalculateRewards();
76 | }
77 |
78 | private void CalculateRewards()
79 | {
80 | float reward = 0f;
81 |
82 | // Reward for satisfying needs
83 | if (npcComponent.needs.hunger < 0.3f) reward += 0.1f;
84 | if (npcComponent.needs.thirst < 0.3f) reward += 0.1f;
85 | if (npcComponent.needs.energy < 0.3f) reward += 0.1f;
86 | if (npcComponent.needs.social < 0.3f) reward += 0.1f;
87 |
88 | // Penalize for critical needs
89 | if (npcComponent.needs.hunger > 0.8f) reward -= 0.2f;
90 | if (npcComponent.needs.thirst > 0.8f) reward -= 0.2f;
91 | if (npcComponent.needs.energy > 0.8f) reward -= 0.2f;
92 | if (npcComponent.needs.social > 0.8f) reward -= 0.2f;
93 |
94 | // Apply the reward
95 | mlAgentComponent.AddReward(reward);
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Assets/Settings/PC_Renderer.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &11400000
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 0
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3}
13 | m_Name: PC_Renderer
14 | m_EditorClassIdentifier:
15 | debugShaders:
16 | debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7,
17 | type: 3}
18 | hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3}
19 | probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959,
20 | type: 3}
21 | probeVolumeResources:
22 | probeVolumeDebugShader: {fileID: 4800000, guid: e5c6678ed2aaa91408dd3df699057aae,
23 | type: 3}
24 | probeVolumeFragmentationDebugShader: {fileID: 4800000, guid: 03cfc4915c15d504a9ed85ecc404e607,
25 | type: 3}
26 | probeVolumeOffsetDebugShader: {fileID: 4800000, guid: 53a11f4ebaebf4049b3638ef78dc9664,
27 | type: 3}
28 | probeVolumeSamplingDebugShader: {fileID: 4800000, guid: 8f96cd657dc40064aa21efcc7e50a2e7,
29 | type: 3}
30 | probeSamplingDebugMesh: {fileID: -3555484719484374845, guid: 57d7c4c16e2765b47a4d2069b311bffe,
31 | type: 3}
32 | probeSamplingDebugTexture: {fileID: 2800000, guid: 24ec0e140fb444a44ab96ee80844e18e,
33 | type: 3}
34 | probeVolumeBlendStatesCS: {fileID: 7200000, guid: b9a23f869c4fd45f19c5ada54dd82176,
35 | type: 3}
36 | m_RendererFeatures:
37 | - {fileID: 7833122117494664109}
38 | m_RendererFeatureMap: ad6b866f10d7b46c
39 | m_UseNativeRenderPass: 1
40 | postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2}
41 | m_AssetVersion: 2
42 | m_OpaqueLayerMask:
43 | serializedVersion: 2
44 | m_Bits: 4294967295
45 | m_TransparentLayerMask:
46 | serializedVersion: 2
47 | m_Bits: 4294967295
48 | m_DefaultStencilState:
49 | overrideStencilState: 0
50 | stencilReference: 1
51 | stencilCompareFunction: 3
52 | passOperation: 2
53 | failOperation: 0
54 | zFailOperation: 0
55 | m_ShadowTransparentReceive: 1
56 | m_RenderingMode: 2
57 | m_DepthPrimingMode: 0
58 | m_CopyDepthMode: 0
59 | m_AccurateGbufferNormals: 0
60 | m_IntermediateTextureMode: 0
61 | --- !u!114 &7833122117494664109
62 | MonoBehaviour:
63 | m_ObjectHideFlags: 0
64 | m_CorrespondingSourceObject: {fileID: 0}
65 | m_PrefabInstance: {fileID: 0}
66 | m_PrefabAsset: {fileID: 0}
67 | m_GameObject: {fileID: 0}
68 | m_Enabled: 1
69 | m_EditorHideFlags: 0
70 | m_Script: {fileID: 11500000, guid: f62c9c65cf3354c93be831c8bc075510, type: 3}
71 | m_Name: ScreenSpaceAmbientOcclusion
72 | m_EditorClassIdentifier:
73 | m_Active: 1
74 | m_Settings:
75 | AOMethod: 0
76 | Downsample: 0
77 | AfterOpaque: 0
78 | Source: 1
79 | NormalSamples: 1
80 | Intensity: 0.4
81 | DirectLightingStrength: 0.25
82 | Radius: 0.3
83 | Samples: 1
84 | BlurQuality: 0
85 | Falloff: 100
86 | SampleCount: -1
87 | m_BlueNoise256Textures:
88 | - {fileID: 2800000, guid: 36f118343fc974119bee3d09e2111500, type: 3}
89 | - {fileID: 2800000, guid: 4b7b083e6b6734e8bb2838b0b50a0bc8, type: 3}
90 | - {fileID: 2800000, guid: c06cc21c692f94f5fb5206247191eeee, type: 3}
91 | - {fileID: 2800000, guid: cb76dd40fa7654f9587f6a344f125c9a, type: 3}
92 | - {fileID: 2800000, guid: e32226222ff144b24bf3a5a451de54bc, type: 3}
93 | - {fileID: 2800000, guid: 3302065f671a8450b82c9ddf07426f3a, type: 3}
94 | - {fileID: 2800000, guid: 56a77a3e8d64f47b6afe9e3c95cb57d5, type: 3}
95 | m_Shader: {fileID: 4800000, guid: 0849e84e3d62649e8882e9d6f056a017, type: 3}
96 |
--------------------------------------------------------------------------------
/ProjectSettings/SceneTemplateSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "templatePinStates": [],
3 | "dependencyTypeInfos": [
4 | {
5 | "userAdded": false,
6 | "type": "UnityEngine.AnimationClip",
7 | "defaultInstantiationMode": 0
8 | },
9 | {
10 | "userAdded": false,
11 | "type": "UnityEditor.Animations.AnimatorController",
12 | "defaultInstantiationMode": 0
13 | },
14 | {
15 | "userAdded": false,
16 | "type": "UnityEngine.AnimatorOverrideController",
17 | "defaultInstantiationMode": 0
18 | },
19 | {
20 | "userAdded": false,
21 | "type": "UnityEditor.Audio.AudioMixerController",
22 | "defaultInstantiationMode": 0
23 | },
24 | {
25 | "userAdded": false,
26 | "type": "UnityEngine.ComputeShader",
27 | "defaultInstantiationMode": 1
28 | },
29 | {
30 | "userAdded": false,
31 | "type": "UnityEngine.Cubemap",
32 | "defaultInstantiationMode": 0
33 | },
34 | {
35 | "userAdded": false,
36 | "type": "UnityEngine.GameObject",
37 | "defaultInstantiationMode": 0
38 | },
39 | {
40 | "userAdded": false,
41 | "type": "UnityEditor.LightingDataAsset",
42 | "defaultInstantiationMode": 0
43 | },
44 | {
45 | "userAdded": false,
46 | "type": "UnityEngine.LightingSettings",
47 | "defaultInstantiationMode": 0
48 | },
49 | {
50 | "userAdded": false,
51 | "type": "UnityEngine.Material",
52 | "defaultInstantiationMode": 0
53 | },
54 | {
55 | "userAdded": false,
56 | "type": "UnityEditor.MonoScript",
57 | "defaultInstantiationMode": 1
58 | },
59 | {
60 | "userAdded": false,
61 | "type": "UnityEngine.PhysicsMaterial",
62 | "defaultInstantiationMode": 0
63 | },
64 | {
65 | "userAdded": false,
66 | "type": "UnityEngine.PhysicsMaterial2D",
67 | "defaultInstantiationMode": 0
68 | },
69 | {
70 | "userAdded": false,
71 | "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile",
72 | "defaultInstantiationMode": 0
73 | },
74 | {
75 | "userAdded": false,
76 | "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources",
77 | "defaultInstantiationMode": 0
78 | },
79 | {
80 | "userAdded": false,
81 | "type": "UnityEngine.Rendering.VolumeProfile",
82 | "defaultInstantiationMode": 0
83 | },
84 | {
85 | "userAdded": false,
86 | "type": "UnityEditor.SceneAsset",
87 | "defaultInstantiationMode": 1
88 | },
89 | {
90 | "userAdded": false,
91 | "type": "UnityEngine.Shader",
92 | "defaultInstantiationMode": 1
93 | },
94 | {
95 | "userAdded": false,
96 | "type": "UnityEngine.ShaderVariantCollection",
97 | "defaultInstantiationMode": 1
98 | },
99 | {
100 | "userAdded": false,
101 | "type": "UnityEngine.Texture",
102 | "defaultInstantiationMode": 0
103 | },
104 | {
105 | "userAdded": false,
106 | "type": "UnityEngine.Texture2D",
107 | "defaultInstantiationMode": 0
108 | },
109 | {
110 | "userAdded": false,
111 | "type": "UnityEngine.Timeline.TimelineAsset",
112 | "defaultInstantiationMode": 0
113 | }
114 | ],
115 | "defaultDependencyTypeInfo": {
116 | "userAdded": false,
117 | "type": "",
118 | "defaultInstantiationMode": 1
119 | },
120 | "newSceneOverride": 0
121 | }
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/Messaging/SystemMessages.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Components;
3 |
4 | namespace ECS.Core.Messaging
5 | {
6 | // Message sent when a system is initialized
7 | public class SystemInitializedMessage : Message
8 | {
9 | public readonly SystemBase System;
10 | public readonly string SystemName;
11 |
12 | public SystemInitializedMessage(SystemBase system) : base(null)
13 | {
14 | System = system;
15 | SystemName = system.GetType().Name;
16 | Priority = MessagePriority.Normal;
17 | }
18 | }
19 |
20 | // Message sent when a resource state changes
21 | public class ResourceStateChangedMessage : Message
22 | {
23 | public readonly Vector3 Position;
24 | public readonly string ResourceType;
25 | public readonly float CurrentQuantity;
26 | public readonly float MaxQuantity;
27 | public readonly bool IsDepleted;
28 |
29 | public ResourceStateChangedMessage(
30 | Entity source,
31 | Vector3 position,
32 | string resourceType,
33 | float currentQuantity,
34 | float maxQuantity,
35 | bool isDepleted
36 | ) : base(source)
37 | {
38 | Position = position;
39 | ResourceType = resourceType;
40 | CurrentQuantity = currentQuantity;
41 | MaxQuantity = maxQuantity;
42 | IsDepleted = isDepleted;
43 | Priority = MessagePriority.Normal;
44 | }
45 | }
46 |
47 | // Message sent when an NPC's needs change significantly
48 | public class NPCNeedsChangedMessage : Message
49 | {
50 | public readonly string NPCName;
51 | public readonly string NeedType;
52 | public readonly float PreviousValue;
53 | public readonly float NewValue;
54 | public readonly bool IsUrgent;
55 |
56 | public NPCNeedsChangedMessage(
57 | Entity source,
58 | string npcName,
59 | string needType,
60 | float previousValue,
61 | float newValue,
62 | bool isUrgent
63 | ) : base(source)
64 | {
65 | NPCName = npcName;
66 | NeedType = needType;
67 | PreviousValue = previousValue;
68 | NewValue = newValue;
69 | IsUrgent = isUrgent;
70 | Priority = isUrgent ? MessagePriority.High : MessagePriority.Normal;
71 | }
72 | }
73 |
74 | // Message sent when terrain generation is complete
75 | public class TerrainChunkGeneratedMessage : Message
76 | {
77 | public readonly Vector2Int ChunkCoord;
78 | public readonly Vector3 WorldPosition;
79 | public readonly TerrainDataComponent.BiomeType PrimaryBiome;
80 |
81 | public TerrainChunkGeneratedMessage(
82 | Entity source,
83 | Vector2Int chunkCoord,
84 | Vector3 worldPosition,
85 | TerrainDataComponent.BiomeType primaryBiome
86 | ) : base(source)
87 | {
88 | ChunkCoord = chunkCoord;
89 | WorldPosition = worldPosition;
90 | PrimaryBiome = primaryBiome;
91 | Priority = MessagePriority.Low;
92 | }
93 | }
94 |
95 | // Message sent when day/night cycle changes
96 | public class TimeChangedMessage : Message
97 | {
98 | public readonly float CurrentTime;
99 | public readonly int CurrentDay;
100 | public readonly TimeComponent.DayPeriod NewPeriod;
101 | public readonly TimeComponent.DayPeriod PreviousPeriod;
102 |
103 | public TimeChangedMessage(
104 | Entity source,
105 | float currentTime,
106 | int currentDay,
107 | TimeComponent.DayPeriod newPeriod,
108 | TimeComponent.DayPeriod previousPeriod
109 | ) : base(source)
110 | {
111 | CurrentTime = currentTime;
112 | CurrentDay = currentDay;
113 | NewPeriod = newPeriod;
114 | PreviousPeriod = previousPeriod;
115 | Priority = MessagePriority.Normal;
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/README_ML_AGENTS.md:
--------------------------------------------------------------------------------
1 | # ML-Agents Integration for NPC System
2 |
3 | This is a proof-of-concept integration of ML-Agents-like functionality with the existing NPC system. It provides a framework for intelligent decision-making that can eventually take over the entire NPC behavior.
4 |
5 | ## Overview
6 |
7 | The integration consists of the following components:
8 |
9 | 1. **MLAgentComponent**: Stores the agent's state, actions, and rewards
10 | 2. **NPCAgent**: Makes decisions based on NPC needs and personality
11 | 3. **MLAgentSystem**: Processes agent decisions and controls NPCs accordingly
12 | 4. **MLAgentSetup**: Helper component to manually add ML-Agent functionality to specific NPCs
13 | 5. **MLAgentSpawnerSystem**: System that automatically adds ML-Agent components to all NPCs in the scene
14 |
15 | ## How to Use
16 |
17 | ### Automatic Setup for All NPCs (Recommended)
18 |
19 | 1. Add the `MLAgentSpawnerSystem` to your scene:
20 | - Create an empty GameObject
21 | - Add the `MLAgentSpawnerSystem` component to it
22 | - Configure the settings as needed:
23 | - **Enable Agent**: Whether to use the ML-Agent for decision making
24 | - **Decision Interval**: How often the agent makes decisions (in seconds)
25 | - **Use Randomness**: Whether to add randomness to decisions based on curiosity
26 |
27 | The system will automatically find all NPCs in the scene and add the required ML-Agent components to them. It will also monitor for new NPCs and add components to them as they are created.
28 |
29 | ### Manual Setup for Specific NPCs
30 |
31 | If you prefer to manually add ML-Agent functionality to specific NPCs:
32 |
33 | 1. Select an NPC GameObject in your scene
34 | 2. Add the `MLAgentSetup` component to the GameObject
35 | 3. Configure the settings as needed:
36 | - **Enable Agent**: Whether to use the ML-Agent for decision making
37 | - **Decision Interval**: How often the agent makes decisions (in seconds)
38 | - **Use Randomness**: Whether to add randomness to decisions based on curiosity
39 |
40 | The setup component will automatically add the required components and configure them.
41 |
42 | ### How It Works
43 |
44 | 1. The `NPCAgent` component observes the NPC's state (needs, personality, etc.)
45 | 2. Based on these observations, it makes a decision (idle, seek food, seek water, etc.)
46 | 3. The `MLAgentSystem` processes this decision and controls the NPC accordingly
47 | 4. The agent receives rewards based on how well it satisfies the NPC's needs
48 |
49 | ### Decision Making
50 |
51 | The agent makes decisions based on the following factors:
52 | - NPC needs (hunger, thirst, energy, social)
53 | - NPC personality (sociability, bravery, curiosity, diligence)
54 | - Current state of the NPC
55 |
56 | The decisions are represented as integers:
57 | - 0: Idle
58 | - 1: Seek Food
59 | - 2: Seek Water
60 | - 3: Seek Rest
61 | - 4: Seek Social
62 |
63 | ### Reward System
64 |
65 | The agent receives rewards based on how well it satisfies the NPC's needs:
66 | - Positive rewards for keeping needs satisfied (below 30%)
67 | - Negative rewards for critical needs (above 80%)
68 |
69 | ## Future Enhancements
70 |
71 | This proof-of-concept can be extended in several ways:
72 |
73 | 1. **Full ML-Agents Integration**: Connect to the actual ML-Agents package for training with reinforcement learning
74 | 2. **More Observations**: Add observations for nearby resources, NPCs, terrain, etc.
75 | 3. **More Actions**: Add more complex actions like working, exploring, etc.
76 | 4. **Hierarchical Decision Making**: Use ML-Agents for high-level decisions and traditional AI for low-level execution
77 | 5. **Multi-Agent Coordination**: Enable coordination between multiple NPCs
78 |
79 | ## Connecting to Unity ML-Agents
80 |
81 | To connect this system to the actual Unity ML-Agents package:
82 |
83 | 1. Install the ML-Agents package from the Package Manager
84 | 2. Update the components to use the ML-Agents API:
85 | - Replace `MLAgentComponent` with the ML-Agents `Agent` class
86 | - Update `NPCAgent` to inherit from `Agent` and implement the required methods
87 | - Update `MLAgentSystem` to work with the ML-Agents framework
88 | - Update `MLAgentSetup` to configure the ML-Agents components
89 |
90 | This will allow you to train the agents using reinforcement learning and other ML techniques provided by the ML-Agents package.
91 |
--------------------------------------------------------------------------------
/ProjectSettings/QualitySettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!47 &1
4 | QualitySettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 5
7 | m_CurrentQuality: 1
8 | m_QualitySettings:
9 | - serializedVersion: 4
10 | name: Mobile
11 | pixelLightCount: 2
12 | shadows: 2
13 | shadowResolution: 1
14 | shadowProjection: 1
15 | shadowCascades: 2
16 | shadowDistance: 40
17 | shadowNearPlaneOffset: 3
18 | shadowCascade2Split: 0.33333334
19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
20 | shadowmaskMode: 0
21 | skinWeights: 2
22 | globalTextureMipmapLimit: 0
23 | textureMipmapLimitSettings: []
24 | anisotropicTextures: 1
25 | antiAliasing: 0
26 | softParticles: 0
27 | softVegetation: 1
28 | realtimeReflectionProbes: 0
29 | billboardsFaceCameraPosition: 1
30 | useLegacyDetailDistribution: 1
31 | adaptiveVsync: 0
32 | vSyncCount: 0
33 | realtimeGICPUUsage: 100
34 | adaptiveVsyncExtraA: 0
35 | adaptiveVsyncExtraB: 0
36 | lodBias: 1
37 | maximumLODLevel: 0
38 | enableLODCrossFade: 1
39 | streamingMipmapsActive: 0
40 | streamingMipmapsAddAllCameras: 1
41 | streamingMipmapsMemoryBudget: 512
42 | streamingMipmapsRenderersPerFrame: 512
43 | streamingMipmapsMaxLevelReduction: 2
44 | streamingMipmapsMaxFileIORequests: 1024
45 | particleRaycastBudget: 256
46 | asyncUploadTimeSlice: 2
47 | asyncUploadBufferSize: 16
48 | asyncUploadPersistentBuffer: 1
49 | resolutionScalingFixedDPIFactor: 1
50 | customRenderPipeline: {fileID: 11400000, guid: 5e6cbd92db86f4b18aec3ed561671858,
51 | type: 2}
52 | terrainQualityOverrides: 0
53 | terrainPixelError: 1
54 | terrainDetailDensityScale: 1
55 | terrainBasemapDistance: 1000
56 | terrainDetailDistance: 80
57 | terrainTreeDistance: 5000
58 | terrainBillboardStart: 50
59 | terrainFadeLength: 5
60 | terrainMaxTrees: 50
61 | excludedTargetPlatforms:
62 | - Standalone
63 | - serializedVersion: 4
64 | name: PC
65 | pixelLightCount: 2
66 | shadows: 2
67 | shadowResolution: 1
68 | shadowProjection: 1
69 | shadowCascades: 2
70 | shadowDistance: 40
71 | shadowNearPlaneOffset: 3
72 | shadowCascade2Split: 0.33333334
73 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
74 | shadowmaskMode: 1
75 | skinWeights: 4
76 | globalTextureMipmapLimit: 0
77 | textureMipmapLimitSettings: []
78 | anisotropicTextures: 2
79 | antiAliasing: 0
80 | softParticles: 0
81 | softVegetation: 1
82 | realtimeReflectionProbes: 0
83 | billboardsFaceCameraPosition: 1
84 | useLegacyDetailDistribution: 1
85 | adaptiveVsync: 0
86 | vSyncCount: 0
87 | realtimeGICPUUsage: 100
88 | adaptiveVsyncExtraA: 0
89 | adaptiveVsyncExtraB: 0
90 | lodBias: 2
91 | maximumLODLevel: 0
92 | enableLODCrossFade: 1
93 | streamingMipmapsActive: 0
94 | streamingMipmapsAddAllCameras: 1
95 | streamingMipmapsMemoryBudget: 512
96 | streamingMipmapsRenderersPerFrame: 512
97 | streamingMipmapsMaxLevelReduction: 2
98 | streamingMipmapsMaxFileIORequests: 1024
99 | particleRaycastBudget: 256
100 | asyncUploadTimeSlice: 2
101 | asyncUploadBufferSize: 16
102 | asyncUploadPersistentBuffer: 1
103 | resolutionScalingFixedDPIFactor: 1
104 | customRenderPipeline: {fileID: 11400000, guid: 4b83569d67af61e458304325a23e5dfd,
105 | type: 2}
106 | terrainQualityOverrides: 0
107 | terrainPixelError: 1
108 | terrainDetailDensityScale: 1
109 | terrainBasemapDistance: 1000
110 | terrainDetailDistance: 80
111 | terrainTreeDistance: 5000
112 | terrainBillboardStart: 50
113 | terrainFadeLength: 5
114 | terrainMaxTrees: 50
115 | excludedTargetPlatforms:
116 | - Android
117 | - iPhone
118 | m_TextureMipmapLimitGroupNames: []
119 | m_PerPlatformDefaultQuality:
120 | Android: 0
121 | GameCoreScarlett: 1
122 | GameCoreXboxOne: 1
123 | Lumin: 0
124 | Nintendo Switch: 1
125 | PS4: 1
126 | PS5: 1
127 | Server: 0
128 | Stadia: 0
129 | Standalone: 1
130 | WebGL: 0
131 | Windows Store Apps: 0
132 | XboxOne: 0
133 | iPhone: 0
134 | tvOS: 0
135 |
--------------------------------------------------------------------------------
/Assets/Shaders/TerrainShader.shader:
--------------------------------------------------------------------------------
1 | Shader "Custom/TerrainShader"
2 | {
3 | Properties
4 | {
5 | _MainTex ("Texture", 2D) = "white" {}
6 | _PlainsColor ("Plains Color", Color) = (0.4, 0.8, 0.4, 1)
7 | _ForestColor ("Forest Color", Color) = (0.2, 0.6, 0.2, 1)
8 | _MountainColor ("Mountain Color", Color) = (0.6, 0.6, 0.6, 1)
9 | _DesertColor ("Desert Color", Color) = (0.9, 0.8, 0.5, 1)
10 | _BlendDistance ("Blend Distance", Float) = 1.0
11 | _HeightBlend ("Height Blend", Range(0, 1)) = 0.5
12 | }
13 | SubShader
14 | {
15 | Tags { "RenderType"="Opaque" }
16 | LOD 100
17 |
18 | Pass
19 | {
20 | CGPROGRAM
21 | #pragma vertex vert
22 | #pragma fragment frag
23 | #pragma multi_compile_instancing
24 | #include "UnityCG.cginc"
25 |
26 | struct appdata
27 | {
28 | float4 vertex : POSITION;
29 | float2 uv : TEXCOORD0;
30 | float4 color : COLOR;
31 | float3 normal : NORMAL;
32 | UNITY_VERTEX_INPUT_INSTANCE_ID
33 | };
34 |
35 | struct v2f
36 | {
37 | float2 uv : TEXCOORD0;
38 | float4 vertex : SV_POSITION;
39 | float4 color : COLOR;
40 | float3 worldPos : TEXCOORD1;
41 | float3 normal : NORMAL;
42 | UNITY_VERTEX_INPUT_INSTANCE_ID
43 | };
44 |
45 | sampler2D _MainTex;
46 | float4 _MainTex_ST;
47 | float4 _PlainsColor;
48 | float4 _ForestColor;
49 | float4 _MountainColor;
50 | float4 _DesertColor;
51 | float _BlendDistance;
52 | float _HeightBlend;
53 |
54 | v2f vert (appdata v)
55 | {
56 | v2f o;
57 | UNITY_SETUP_INSTANCE_ID(v);
58 | UNITY_TRANSFER_INSTANCE_ID(v, o);
59 |
60 | o.vertex = UnityObjectToClipPos(v.vertex);
61 | o.uv = TRANSFORM_TEX(v.uv, _MainTex);
62 | o.color = v.color;
63 | o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
64 | o.normal = UnityObjectToWorldNormal(v.normal);
65 | return o;
66 | }
67 |
68 | float4 BlendBiomeColors(float4 baseColor, float height)
69 | {
70 | // Get biome weights from vertex color
71 | float plains = baseColor.r;
72 | float forest = baseColor.g;
73 | float mountain = baseColor.b;
74 |
75 | // Apply height-based blending
76 | float heightFactor = saturate((height + _HeightBlend) / (1 + _HeightBlend));
77 |
78 | // Blend colors based on height and biome weights
79 | float4 finalColor = float4(0,0,0,1);
80 | finalColor += _PlainsColor * plains * (1 - heightFactor);
81 | finalColor += _ForestColor * forest;
82 | finalColor += _MountainColor * mountain * heightFactor;
83 |
84 | // Normalize
85 | finalColor.rgb /= (plains + forest + mountain);
86 |
87 | return finalColor;
88 | }
89 |
90 | fixed4 frag (v2f i) : SV_Target
91 | {
92 | UNITY_SETUP_INSTANCE_ID(i);
93 |
94 | // Sample base texture
95 | fixed4 col = tex2D(_MainTex, i.uv);
96 |
97 | // Get world height
98 | float height = i.worldPos.y;
99 |
100 | // Blend biome colors
101 | float4 biomeColor = BlendBiomeColors(i.color, height);
102 |
103 | // Apply normal-based shading
104 | float3 normal = normalize(i.normal);
105 | float ndotl = saturate(dot(normal, _WorldSpaceLightPos0.xyz));
106 | float lighting = ndotl * 0.5 + 0.5; // Soften the lighting
107 |
108 | // Apply lighting to final color
109 | return biomeColor * lighting;
110 | }
111 | ENDCG
112 | }
113 | }
114 | FallBack "Diffuse"
115 | }
116 |
--------------------------------------------------------------------------------
/Assets/Settings/SampleSceneProfile.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &-7893295128165547882
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 3
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: 0b2db86121404754db890f4c8dfe81b2, type: 3}
13 | m_Name: Bloom
14 | m_EditorClassIdentifier:
15 | active: 1
16 | skipIterations:
17 | m_OverrideState: 1
18 | m_Value: 0
19 | threshold:
20 | m_OverrideState: 1
21 | m_Value: 1
22 | intensity:
23 | m_OverrideState: 1
24 | m_Value: 0.25
25 | scatter:
26 | m_OverrideState: 1
27 | m_Value: 0.5
28 | clamp:
29 | m_OverrideState: 0
30 | m_Value: 65472
31 | tint:
32 | m_OverrideState: 0
33 | m_Value: {r: 1, g: 1, b: 1, a: 1}
34 | highQualityFiltering:
35 | m_OverrideState: 1
36 | m_Value: 1
37 | downscale:
38 | m_OverrideState: 0
39 | m_Value: 0
40 | maxIterations:
41 | m_OverrideState: 0
42 | m_Value: 6
43 | dirtTexture:
44 | m_OverrideState: 0
45 | m_Value: {fileID: 0}
46 | dimension: 1
47 | dirtIntensity:
48 | m_OverrideState: 0
49 | m_Value: 0
50 | --- !u!114 &-3357603926938260329
51 | MonoBehaviour:
52 | m_ObjectHideFlags: 3
53 | m_CorrespondingSourceObject: {fileID: 0}
54 | m_PrefabInstance: {fileID: 0}
55 | m_PrefabAsset: {fileID: 0}
56 | m_GameObject: {fileID: 0}
57 | m_Enabled: 1
58 | m_EditorHideFlags: 0
59 | m_Script: {fileID: 11500000, guid: 899c54efeace73346a0a16faa3afe726, type: 3}
60 | m_Name: Vignette
61 | m_EditorClassIdentifier:
62 | active: 1
63 | color:
64 | m_OverrideState: 0
65 | m_Value: {r: 0, g: 0, b: 0, a: 1}
66 | center:
67 | m_OverrideState: 0
68 | m_Value: {x: 0.5, y: 0.5}
69 | intensity:
70 | m_OverrideState: 1
71 | m_Value: 0.2
72 | smoothness:
73 | m_OverrideState: 0
74 | m_Value: 0.2
75 | rounded:
76 | m_OverrideState: 0
77 | m_Value: 0
78 | --- !u!114 &11400000
79 | MonoBehaviour:
80 | m_ObjectHideFlags: 0
81 | m_CorrespondingSourceObject: {fileID: 0}
82 | m_PrefabInstance: {fileID: 0}
83 | m_PrefabAsset: {fileID: 0}
84 | m_GameObject: {fileID: 0}
85 | m_Enabled: 1
86 | m_EditorHideFlags: 0
87 | m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3}
88 | m_Name: SampleSceneProfile
89 | m_EditorClassIdentifier:
90 | components:
91 | - {fileID: 849379129802519247}
92 | - {fileID: -7893295128165547882}
93 | - {fileID: 7391319092446245454}
94 | - {fileID: -3357603926938260329}
95 | --- !u!114 &849379129802519247
96 | MonoBehaviour:
97 | m_ObjectHideFlags: 3
98 | m_CorrespondingSourceObject: {fileID: 0}
99 | m_PrefabInstance: {fileID: 0}
100 | m_PrefabAsset: {fileID: 0}
101 | m_GameObject: {fileID: 0}
102 | m_Enabled: 1
103 | m_EditorHideFlags: 0
104 | m_Script: {fileID: 11500000, guid: 97c23e3b12dc18c42a140437e53d3951, type: 3}
105 | m_Name: Tonemapping
106 | m_EditorClassIdentifier:
107 | active: 1
108 | mode:
109 | m_OverrideState: 1
110 | m_Value: 1
111 | neutralHDRRangeReductionMode:
112 | m_OverrideState: 0
113 | m_Value: 2
114 | acesPreset:
115 | m_OverrideState: 0
116 | m_Value: 3
117 | hueShiftAmount:
118 | m_OverrideState: 0
119 | m_Value: 0
120 | detectPaperWhite:
121 | m_OverrideState: 1
122 | m_Value: 0
123 | paperWhite:
124 | m_OverrideState: 1
125 | m_Value: 234
126 | detectBrightnessLimits:
127 | m_OverrideState: 1
128 | m_Value: 1
129 | minNits:
130 | m_OverrideState: 1
131 | m_Value: 0.005
132 | maxNits:
133 | m_OverrideState: 1
134 | m_Value: 647
135 | --- !u!114 &7391319092446245454
136 | MonoBehaviour:
137 | m_ObjectHideFlags: 3
138 | m_CorrespondingSourceObject: {fileID: 0}
139 | m_PrefabInstance: {fileID: 0}
140 | m_PrefabAsset: {fileID: 0}
141 | m_GameObject: {fileID: 0}
142 | m_Enabled: 1
143 | m_EditorHideFlags: 0
144 | m_Script: {fileID: 11500000, guid: ccf1aba9553839d41ae37dd52e9ebcce, type: 3}
145 | m_Name: MotionBlur
146 | m_EditorClassIdentifier:
147 | active: 0
148 | mode:
149 | m_OverrideState: 0
150 | m_Value: 0
151 | quality:
152 | m_OverrideState: 1
153 | m_Value: 2
154 | intensity:
155 | m_OverrideState: 1
156 | m_Value: 0.6
157 | clamp:
158 | m_OverrideState: 0
159 | m_Value: 0.05
160 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/Messaging/MessageBus.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace ECS.Core.Messaging
7 | {
8 | public class MessageBus
9 | {
10 | // Dictionary to store message handlers by type
11 | private readonly Dictionary>> handlers = new Dictionary>>();
12 |
13 | // Queue for handling messages in order
14 | private readonly Queue messageQueue = new Queue();
15 |
16 | // Lock object for thread safety
17 | private readonly object queueLock = new object();
18 |
19 | // Subscribe to a specific message type
20 | public void Subscribe(Action handler) where T : Message
21 | {
22 | var messageType = typeof(T);
23 |
24 | if (!handlers.ContainsKey(messageType))
25 | {
26 | handlers[messageType] = new List>();
27 | }
28 |
29 | // Wrap the typed handler in a Message handler
30 | void MessageHandler(Message message) => handler((T)message);
31 | handlers[messageType].Add(MessageHandler);
32 |
33 | Debug.Log($"[MessageBus] Subscribed to {messageType.Name}");
34 | }
35 |
36 | // Unsubscribe from a specific message type
37 | public void Unsubscribe(Action handler) where T : Message
38 | {
39 | var messageType = typeof(T);
40 |
41 | if (handlers.ContainsKey(messageType))
42 | {
43 | // Remove all instances of this handler
44 | handlers[messageType].RemoveAll(h => h.Target == handler.Target && h.Method == handler.Method);
45 |
46 | // Remove the type entry if no handlers remain
47 | if (handlers[messageType].Count == 0)
48 | {
49 | handlers.Remove(messageType);
50 | }
51 |
52 | Debug.Log($"[MessageBus] Unsubscribed from {messageType.Name}");
53 | }
54 | }
55 |
56 | // Publish a message to all subscribers
57 | public void Publish(T message) where T : Message
58 | {
59 | if (message == null)
60 | {
61 | Debug.LogError("[MessageBus] Attempted to publish null message");
62 | return;
63 | }
64 |
65 | var messageType = message.GetType();
66 |
67 | lock (queueLock)
68 | {
69 | messageQueue.Enqueue(message);
70 | }
71 |
72 | Debug.Log($"[MessageBus] Published {messageType.Name} (ID: {message.Id})");
73 | }
74 |
75 | // Process all queued messages
76 | public void ProcessMessages()
77 | {
78 | lock (queueLock)
79 | {
80 | // Process messages by priority
81 | var messages = messageQueue.ToList()
82 | .OrderByDescending(m => m.Priority)
83 | .ThenBy(m => m.Timestamp);
84 |
85 | messageQueue.Clear();
86 |
87 | foreach (var message in messages)
88 | {
89 | var messageType = message.GetType();
90 |
91 | if (handlers.ContainsKey(messageType))
92 | {
93 | foreach (var handler in handlers[messageType])
94 | {
95 | try
96 | {
97 | handler(message);
98 | }
99 | catch (Exception e)
100 | {
101 | Debug.LogError($"[MessageBus] Error processing {messageType.Name}: {e}");
102 | }
103 | }
104 | }
105 | }
106 | }
107 | }
108 |
109 | // Clear all subscriptions
110 | public void ClearSubscriptions()
111 | {
112 | handlers.Clear();
113 | Debug.Log("[MessageBus] Cleared all subscriptions");
114 | }
115 |
116 | // Get number of subscribers for a message type
117 | public int GetSubscriberCount() where T : Message
118 | {
119 | var messageType = typeof(T);
120 | return handlers.ContainsKey(messageType) ? handlers[messageType].Count : 0;
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/ResourceComponent.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 |
4 | namespace ECS.Components
5 | {
6 | public class ResourceComponent : ComponentBase
7 | {
8 | public enum ResourceType
9 | {
10 | Food,
11 | Water,
12 | RestArea,
13 | WorkArea
14 | }
15 |
16 | [System.Serializable]
17 | public class ResourceProperties
18 | {
19 | public float quantity = 100f; // How much resource is available
20 | public float replenishRate = 1f; // Units per second when replenishing
21 | public float consumptionRate = 10f; // Units per second when being consumed
22 | public float qualityMultiplier = 1f; // How effective the resource is (1 = normal)
23 | public bool isInfinite = false; // Whether the resource depletes
24 | public bool autoReplenish = true; // Whether it automatically replenishes
25 | public float replenishDelay = 60f; // Time to wait before replenishing
26 | }
27 |
28 | [Header("Resource Settings")]
29 | public ResourceType type;
30 | public ResourceProperties properties = new ResourceProperties();
31 |
32 | [Header("Status")]
33 | public bool isBeingUsed = false;
34 | public bool isDepleted = false;
35 | private float lastUsedTime;
36 | private float currentQuantity;
37 |
38 | protected override void Awake()
39 | {
40 | base.Awake();
41 | currentQuantity = properties.quantity;
42 | }
43 |
44 | public bool CanBeUsed()
45 | {
46 | return !isDepleted && (!isBeingUsed || type == ResourceType.RestArea);
47 | }
48 |
49 | public void StartUsing()
50 | {
51 | isBeingUsed = true;
52 | lastUsedTime = Time.time;
53 | }
54 |
55 | public void StopUsing()
56 | {
57 | isBeingUsed = false;
58 | lastUsedTime = Time.time;
59 | }
60 |
61 | public float Consume(float deltaTime)
62 | {
63 | if (properties.isInfinite)
64 | {
65 | return properties.consumptionRate * deltaTime * properties.qualityMultiplier;
66 | }
67 |
68 | float amount = Mathf.Min(
69 | properties.consumptionRate * deltaTime,
70 | currentQuantity
71 | ) * properties.qualityMultiplier;
72 |
73 | currentQuantity -= amount;
74 |
75 | if (currentQuantity <= 0)
76 | {
77 | currentQuantity = 0;
78 | isDepleted = true;
79 | }
80 |
81 | return amount;
82 | }
83 |
84 | public void Replenish(float deltaTime)
85 | {
86 | if (isDepleted || !properties.autoReplenish || properties.isInfinite)
87 | return;
88 |
89 | // Only replenish after delay
90 | if (Time.time - lastUsedTime < properties.replenishDelay)
91 | return;
92 |
93 | currentQuantity += properties.replenishRate * deltaTime;
94 |
95 | if (currentQuantity >= properties.quantity)
96 | {
97 | currentQuantity = properties.quantity;
98 | isDepleted = false;
99 | }
100 | }
101 |
102 | public float GetQuantityPercentage()
103 | {
104 | return properties.isInfinite ? 1f : currentQuantity / properties.quantity;
105 | }
106 |
107 | // Visual feedback
108 | private void OnDrawGizmos()
109 | {
110 | // Draw different colored spheres based on resource type
111 | switch (type)
112 | {
113 | case ResourceType.Food:
114 | Gizmos.color = Color.green;
115 | break;
116 | case ResourceType.Water:
117 | Gizmos.color = Color.blue;
118 | break;
119 | case ResourceType.RestArea:
120 | Gizmos.color = Color.yellow;
121 | break;
122 | case ResourceType.WorkArea:
123 | Gizmos.color = Color.gray;
124 | break;
125 | }
126 |
127 | // Fade color if depleted
128 | if (isDepleted)
129 | {
130 | Color c = Gizmos.color;
131 | c.a = 0.3f;
132 | Gizmos.color = c;
133 | }
134 |
135 | Gizmos.DrawWireSphere(transform.position, 1f);
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/Assets/Settings/Mobile_RPAsset.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &11400000
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 0
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3}
13 | m_Name: Mobile_RPAsset
14 | m_EditorClassIdentifier:
15 | k_AssetVersion: 12
16 | k_AssetPreviousVersion: 12
17 | m_RendererType: 1
18 | m_RendererData: {fileID: 0}
19 | m_RendererDataList:
20 | - {fileID: 11400000, guid: 65bc7dbf4170f435aa868c779acfb082, type: 2}
21 | m_DefaultRendererIndex: 0
22 | m_RequireDepthTexture: 0
23 | m_RequireOpaqueTexture: 0
24 | m_OpaqueDownsampling: 0
25 | m_SupportsTerrainHoles: 1
26 | m_SupportsHDR: 1
27 | m_HDRColorBufferPrecision: 0
28 | m_MSAA: 1
29 | m_RenderScale: 0.8
30 | m_UpscalingFilter: 3
31 | m_FsrOverrideSharpness: 0
32 | m_FsrSharpness: 0.92
33 | m_EnableLODCrossFade: 1
34 | m_LODCrossFadeDitheringType: 1
35 | m_ShEvalMode: 0
36 | m_LightProbeSystem: 0
37 | m_ProbeVolumeMemoryBudget: 1024
38 | m_ProbeVolumeBlendingMemoryBudget: 256
39 | m_SupportProbeVolumeGPUStreaming: 0
40 | m_SupportProbeVolumeDiskStreaming: 0
41 | m_SupportProbeVolumeScenarios: 0
42 | m_SupportProbeVolumeScenarioBlending: 0
43 | m_ProbeVolumeSHBands: 1
44 | m_MainLightRenderingMode: 1
45 | m_MainLightShadowsSupported: 1
46 | m_MainLightShadowmapResolution: 1024
47 | m_AdditionalLightsRenderingMode: 1
48 | m_AdditionalLightsPerObjectLimit: 4
49 | m_AdditionalLightShadowsSupported: 0
50 | m_AdditionalLightsShadowmapResolution: 2048
51 | m_AdditionalLightsShadowResolutionTierLow: 256
52 | m_AdditionalLightsShadowResolutionTierMedium: 512
53 | m_AdditionalLightsShadowResolutionTierHigh: 1024
54 | m_ReflectionProbeBlending: 1
55 | m_ReflectionProbeBoxProjection: 1
56 | m_ShadowDistance: 50
57 | m_ShadowCascadeCount: 1
58 | m_Cascade2Split: 0.25
59 | m_Cascade3Split: {x: 0.1, y: 0.3}
60 | m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467}
61 | m_CascadeBorder: 0.2
62 | m_ShadowDepthBias: 1
63 | m_ShadowNormalBias: 1
64 | m_AnyShadowsSupported: 1
65 | m_SoftShadowsSupported: 0
66 | m_ConservativeEnclosingSphere: 1
67 | m_NumIterationsEnclosingSphere: 64
68 | m_SoftShadowQuality: 2
69 | m_AdditionalLightsCookieResolution: 1024
70 | m_AdditionalLightsCookieFormat: 1
71 | m_UseSRPBatcher: 1
72 | m_SupportsDynamicBatching: 0
73 | m_MixedLightingSupported: 1
74 | m_SupportsLightCookies: 1
75 | m_SupportsLightLayers: 1
76 | m_DebugLevel: 0
77 | m_StoreActionsOptimization: 0
78 | m_UseAdaptivePerformance: 1
79 | m_ColorGradingMode: 0
80 | m_ColorGradingLutSize: 32
81 | m_UseFastSRGBLinearConversion: 1
82 | m_SupportDataDrivenLensFlare: 1
83 | m_SupportScreenSpaceLensFlare: 1
84 | m_GPUResidentDrawerMode: 0
85 | m_UseLegacyLightmaps: 0
86 | m_SmallMeshScreenPercentage: 0
87 | m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0
88 | m_ShadowType: 1
89 | m_LocalShadowsSupported: 0
90 | m_LocalShadowsAtlasResolution: 256
91 | m_MaxPixelLights: 0
92 | m_ShadowAtlasResolution: 256
93 | m_VolumeFrameworkUpdateMode: 0
94 | m_VolumeProfile: {fileID: 11400000, guid: 10fc4df2da32a41aaa32d77bc913491c, type: 2}
95 | apvScenesData:
96 | obsoleteSceneBounds:
97 | m_Keys: []
98 | m_Values: []
99 | obsoleteHasProbeVolumes:
100 | m_Keys: []
101 | m_Values:
102 | m_PrefilteringModeMainLightShadows: 3
103 | m_PrefilteringModeAdditionalLight: 4
104 | m_PrefilteringModeAdditionalLightShadows: 0
105 | m_PrefilterXRKeywords: 1
106 | m_PrefilteringModeForwardPlus: 1
107 | m_PrefilteringModeDeferredRendering: 0
108 | m_PrefilteringModeScreenSpaceOcclusion: 0
109 | m_PrefilterDebugKeywords: 1
110 | m_PrefilterWriteRenderingLayers: 1
111 | m_PrefilterHDROutput: 1
112 | m_PrefilterSSAODepthNormals: 1
113 | m_PrefilterSSAOSourceDepthLow: 1
114 | m_PrefilterSSAOSourceDepthMedium: 0
115 | m_PrefilterSSAOSourceDepthHigh: 1
116 | m_PrefilterSSAOInterleaved: 0
117 | m_PrefilterSSAOBlueNoise: 1
118 | m_PrefilterSSAOSampleCountLow: 1
119 | m_PrefilterSSAOSampleCountMedium: 0
120 | m_PrefilterSSAOSampleCountHigh: 1
121 | m_PrefilterDBufferMRT1: 1
122 | m_PrefilterDBufferMRT2: 1
123 | m_PrefilterDBufferMRT3: 1
124 | m_PrefilterSoftShadowsQualityLow: 1
125 | m_PrefilterSoftShadowsQualityMedium: 1
126 | m_PrefilterSoftShadowsQualityHigh: 1
127 | m_PrefilterSoftShadows: 0
128 | m_PrefilterScreenCoord: 1
129 | m_PrefilterNativeRenderPass: 1
130 | m_PrefilterUseLegacyLightmaps: 0
131 | m_ShaderVariantLogLevel: 0
132 | m_ShadowCascades: 0
133 | m_Textures:
134 | blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3}
135 | bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3}
136 |
--------------------------------------------------------------------------------
/Assets/Settings/PC_RPAsset.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &11400000
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 0
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3}
13 | m_Name: PC_RPAsset
14 | m_EditorClassIdentifier:
15 | k_AssetVersion: 12
16 | k_AssetPreviousVersion: 12
17 | m_RendererType: 1
18 | m_RendererData: {fileID: 0}
19 | m_RendererDataList:
20 | - {fileID: 11400000, guid: f288ae1f4751b564a96ac7587541f7a2, type: 2}
21 | m_DefaultRendererIndex: 0
22 | m_RequireDepthTexture: 1
23 | m_RequireOpaqueTexture: 1
24 | m_OpaqueDownsampling: 1
25 | m_SupportsTerrainHoles: 1
26 | m_SupportsHDR: 1
27 | m_HDRColorBufferPrecision: 0
28 | m_MSAA: 1
29 | m_RenderScale: 1
30 | m_UpscalingFilter: 0
31 | m_FsrOverrideSharpness: 0
32 | m_FsrSharpness: 0.92
33 | m_EnableLODCrossFade: 1
34 | m_LODCrossFadeDitheringType: 1
35 | m_ShEvalMode: 0
36 | m_LightProbeSystem: 0
37 | m_ProbeVolumeMemoryBudget: 1024
38 | m_ProbeVolumeBlendingMemoryBudget: 256
39 | m_SupportProbeVolumeGPUStreaming: 0
40 | m_SupportProbeVolumeDiskStreaming: 0
41 | m_SupportProbeVolumeScenarios: 0
42 | m_SupportProbeVolumeScenarioBlending: 0
43 | m_ProbeVolumeSHBands: 1
44 | m_MainLightRenderingMode: 1
45 | m_MainLightShadowsSupported: 1
46 | m_MainLightShadowmapResolution: 2048
47 | m_AdditionalLightsRenderingMode: 1
48 | m_AdditionalLightsPerObjectLimit: 4
49 | m_AdditionalLightShadowsSupported: 1
50 | m_AdditionalLightsShadowmapResolution: 2048
51 | m_AdditionalLightsShadowResolutionTierLow: 256
52 | m_AdditionalLightsShadowResolutionTierMedium: 512
53 | m_AdditionalLightsShadowResolutionTierHigh: 1024
54 | m_ReflectionProbeBlending: 1
55 | m_ReflectionProbeBoxProjection: 1
56 | m_ShadowDistance: 50
57 | m_ShadowCascadeCount: 4
58 | m_Cascade2Split: 0.25
59 | m_Cascade3Split: {x: 0.1, y: 0.3}
60 | m_Cascade4Split: {x: 0.12299999, y: 0.2926, z: 0.53599995}
61 | m_CascadeBorder: 0.107758604
62 | m_ShadowDepthBias: 0.1
63 | m_ShadowNormalBias: 0.5
64 | m_AnyShadowsSupported: 1
65 | m_SoftShadowsSupported: 1
66 | m_ConservativeEnclosingSphere: 1
67 | m_NumIterationsEnclosingSphere: 64
68 | m_SoftShadowQuality: 3
69 | m_AdditionalLightsCookieResolution: 2048
70 | m_AdditionalLightsCookieFormat: 3
71 | m_UseSRPBatcher: 1
72 | m_SupportsDynamicBatching: 0
73 | m_MixedLightingSupported: 1
74 | m_SupportsLightCookies: 1
75 | m_SupportsLightLayers: 1
76 | m_DebugLevel: 0
77 | m_StoreActionsOptimization: 0
78 | m_UseAdaptivePerformance: 1
79 | m_ColorGradingMode: 0
80 | m_ColorGradingLutSize: 32
81 | m_UseFastSRGBLinearConversion: 0
82 | m_SupportDataDrivenLensFlare: 1
83 | m_SupportScreenSpaceLensFlare: 1
84 | m_GPUResidentDrawerMode: 0
85 | m_UseLegacyLightmaps: 0
86 | m_SmallMeshScreenPercentage: 0
87 | m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0
88 | m_ShadowType: 1
89 | m_LocalShadowsSupported: 0
90 | m_LocalShadowsAtlasResolution: 256
91 | m_MaxPixelLights: 0
92 | m_ShadowAtlasResolution: 256
93 | m_VolumeFrameworkUpdateMode: 0
94 | m_VolumeProfile: {fileID: 11400000, guid: 10fc4df2da32a41aaa32d77bc913491c, type: 2}
95 | apvScenesData:
96 | obsoleteSceneBounds:
97 | m_Keys: []
98 | m_Values: []
99 | obsoleteHasProbeVolumes:
100 | m_Keys: []
101 | m_Values:
102 | m_PrefilteringModeMainLightShadows: 3
103 | m_PrefilteringModeAdditionalLight: 4
104 | m_PrefilteringModeAdditionalLightShadows: 0
105 | m_PrefilterXRKeywords: 1
106 | m_PrefilteringModeForwardPlus: 1
107 | m_PrefilteringModeDeferredRendering: 0
108 | m_PrefilteringModeScreenSpaceOcclusion: 1
109 | m_PrefilterDebugKeywords: 1
110 | m_PrefilterWriteRenderingLayers: 0
111 | m_PrefilterHDROutput: 1
112 | m_PrefilterSSAODepthNormals: 0
113 | m_PrefilterSSAOSourceDepthLow: 1
114 | m_PrefilterSSAOSourceDepthMedium: 1
115 | m_PrefilterSSAOSourceDepthHigh: 1
116 | m_PrefilterSSAOInterleaved: 1
117 | m_PrefilterSSAOBlueNoise: 0
118 | m_PrefilterSSAOSampleCountLow: 1
119 | m_PrefilterSSAOSampleCountMedium: 0
120 | m_PrefilterSSAOSampleCountHigh: 1
121 | m_PrefilterDBufferMRT1: 1
122 | m_PrefilterDBufferMRT2: 1
123 | m_PrefilterDBufferMRT3: 0
124 | m_PrefilterSoftShadowsQualityLow: 0
125 | m_PrefilterSoftShadowsQualityMedium: 0
126 | m_PrefilterSoftShadowsQualityHigh: 0
127 | m_PrefilterSoftShadows: 0
128 | m_PrefilterScreenCoord: 1
129 | m_PrefilterNativeRenderPass: 1
130 | m_PrefilterUseLegacyLightmaps: 0
131 | m_ShaderVariantLogLevel: 0
132 | m_ShadowCascades: 0
133 | m_Textures:
134 | blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3}
135 | bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3}
136 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/Entity.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections.Generic;
3 |
4 | namespace ECS.Core
5 | {
6 | public class Entity : MonoBehaviour
7 | {
8 | private WorldManager worldManager;
9 | private HashSet components = new HashSet();
10 | private HashSet registeredSystems = new HashSet();
11 |
12 | private void Awake()
13 | {
14 | // Find world manager
15 | worldManager = Object.FindFirstObjectByType(FindObjectsInactive.Include);
16 | if (worldManager == null)
17 | {
18 | var go = new GameObject("World Manager");
19 | worldManager = go.AddComponent();
20 | Debug.Log($"[Entity:{gameObject.name}] Created WorldManager automatically");
21 | }
22 |
23 | // Register with world manager
24 | if (worldManager != null)
25 | {
26 | worldManager.RegisterEntity(this);
27 | Debug.Log($"[Entity:{gameObject.name}] Registered with WorldManager");
28 | }
29 | else
30 | {
31 | Debug.LogError($"[Entity:{gameObject.name}] Failed to find or create WorldManager");
32 | }
33 | }
34 |
35 | private void OnDestroy()
36 | {
37 | // Unregister from world manager
38 | if (worldManager != null)
39 | {
40 | worldManager.UnregisterEntity(this);
41 | Debug.Log($"[Entity:{gameObject.name}] Unregistered from WorldManager");
42 | }
43 |
44 | // Unregister from all systems
45 | foreach (var system in registeredSystems)
46 | {
47 | system.UnregisterEntity(this);
48 | Debug.Log($"[Entity:{gameObject.name}] Unregistered from {system.GetType().Name}");
49 | }
50 | registeredSystems.Clear();
51 | }
52 |
53 | public void RegisterComponent(ComponentBase component)
54 | {
55 | if (component != null && !components.Contains(component))
56 | {
57 | components.Add(component);
58 | Debug.Log($"[Entity:{gameObject.name}] Registered component: {component.GetType().Name}");
59 |
60 | // Notify world manager of new component
61 | if (worldManager != null)
62 | {
63 | worldManager.OnEntityComponentAdded(this, component);
64 | }
65 | }
66 | }
67 |
68 | public void UnregisterComponent(ComponentBase component)
69 | {
70 | if (component != null && components.Contains(component))
71 | {
72 | components.Remove(component);
73 | Debug.Log($"[Entity:{gameObject.name}] Unregistered component: {component.GetType().Name}");
74 |
75 | // Notify world manager of removed component
76 | if (worldManager != null)
77 | {
78 | worldManager.OnEntityComponentRemoved(this, component);
79 | }
80 | }
81 | }
82 |
83 | public void RegisterWithSystem(SystemBase system)
84 | {
85 | if (system != null && !registeredSystems.Contains(system))
86 | {
87 | registeredSystems.Add(system);
88 | Debug.Log($"[Entity:{gameObject.name}] Registered with system: {system.GetType().Name}");
89 | }
90 | }
91 |
92 | public void UnregisterFromSystem(SystemBase system)
93 | {
94 | if (system != null && registeredSystems.Contains(system))
95 | {
96 | registeredSystems.Remove(system);
97 | Debug.Log($"[Entity:{gameObject.name}] Unregistered from system: {system.GetType().Name}");
98 | }
99 | }
100 |
101 | public new T GetComponent() where T : ComponentBase
102 | {
103 | foreach (var component in components)
104 | {
105 | if (component is T typedComponent)
106 | {
107 | return typedComponent;
108 | }
109 | }
110 | return null;
111 | }
112 |
113 | public bool HasComponent() where T : ComponentBase
114 | {
115 | foreach (var component in components)
116 | {
117 | if (component is T)
118 | {
119 | return true;
120 | }
121 | }
122 | return false;
123 | }
124 |
125 | public IEnumerable GetAllComponents()
126 | {
127 | return components;
128 | }
129 |
130 | public IEnumerable GetRegisteredSystems()
131 | {
132 | return registeredSystems;
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/TimeSystem.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 | using ECS.Components;
4 | using ECS.Core.Messaging;
5 |
6 | namespace ECS.Systems
7 | {
8 | public class TimeSystem : SystemBase
9 | {
10 | [Header("Time Settings")]
11 | [SerializeField] private float dayLengthInMinutes = 24f;
12 | [SerializeField] private float dawnDuskLengthInMinutes = 1f;
13 |
14 | private float currentTime;
15 | private int currentDay;
16 | private TimeComponent.DayPeriod currentPeriod;
17 |
18 | private float minutesPerSecond;
19 | private float dawnTime;
20 | private float dayTime;
21 | private float duskTime;
22 | private float nightTime;
23 |
24 | protected override void Initialize()
25 | {
26 | // Calculate time constants
27 | minutesPerSecond = 24f / (dayLengthInMinutes * 60f);
28 |
29 | // Set period times (in hours)
30 | dawnTime = 6f; // 6 AM
31 | dayTime = dawnTime + dawnDuskLengthInMinutes / 60f;
32 | duskTime = 18f; // 6 PM
33 | nightTime = duskTime + dawnDuskLengthInMinutes / 60f;
34 |
35 | // Initialize time
36 | currentTime = dawnTime;
37 | currentDay = 1;
38 | currentPeriod = TimeComponent.DayPeriod.Dawn;
39 |
40 | Debug.Log($"TimeSystem initialized: Day {currentDay}, Time {currentTime:F1}, Period {currentPeriod}");
41 | base.Initialize();
42 | }
43 |
44 | public override void UpdateSystem()
45 | {
46 | if (!isInitialized)
47 | {
48 | Initialize();
49 | return;
50 | }
51 |
52 | // Update time
53 | currentTime += Time.deltaTime * minutesPerSecond;
54 |
55 | // Handle day rollover
56 | if (currentTime >= 24f)
57 | {
58 | currentTime -= 24f;
59 | currentDay++;
60 | Debug.Log($"New day started: Day {currentDay}");
61 | }
62 |
63 | // Update period
64 | UpdateDayPeriod();
65 |
66 | // Update all registered entities
67 | foreach (var entity in registeredEntities)
68 | {
69 | var timeComponent = entity.GetComponent();
70 | if (timeComponent != null)
71 | {
72 | timeComponent.UpdateTime(currentTime, currentDay, currentPeriod);
73 | }
74 | }
75 | }
76 |
77 | private void UpdateDayPeriod()
78 | {
79 | TimeComponent.DayPeriod newPeriod = currentPeriod;
80 |
81 | if (currentTime >= dawnTime && currentTime < dayTime)
82 | {
83 | newPeriod = TimeComponent.DayPeriod.Dawn;
84 | }
85 | else if (currentTime >= dayTime && currentTime < duskTime)
86 | {
87 | newPeriod = TimeComponent.DayPeriod.Day;
88 | }
89 | else if (currentTime >= duskTime && currentTime < nightTime)
90 | {
91 | newPeriod = TimeComponent.DayPeriod.Dusk;
92 | }
93 | else
94 | {
95 | newPeriod = TimeComponent.DayPeriod.Night;
96 | }
97 |
98 | if (newPeriod != currentPeriod)
99 | {
100 | var oldPeriod = currentPeriod;
101 | currentPeriod = newPeriod;
102 |
103 | // Publish time changed message
104 | PublishMessage(new TimeChangedMessage(
105 | null,
106 | currentTime,
107 | currentDay,
108 | newPeriod,
109 | oldPeriod
110 | ));
111 |
112 | OnPeriodChanged();
113 | }
114 | }
115 |
116 | protected virtual void OnPeriodChanged()
117 | {
118 | Debug.Log($"Day {currentDay}: Period changed to {currentPeriod} at {currentTime:F1}");
119 | }
120 |
121 | public override void RegisterEntity(Entity entity)
122 | {
123 | if (entity.HasComponent())
124 | {
125 | base.RegisterEntity(entity);
126 |
127 | // Initialize the time component
128 | var timeComponent = entity.GetComponent();
129 | timeComponent.UpdateTime(currentTime, currentDay, currentPeriod);
130 | }
131 | }
132 |
133 | // Public getters for other systems to access time information
134 | public float GetCurrentTime() => currentTime;
135 | public int GetCurrentDay() => currentDay;
136 | public TimeComponent.DayPeriod GetCurrentPeriod() => currentPeriod;
137 | public float GetDayProgress() => (currentTime - dawnTime) / (24f - dawnTime);
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/MLAgentSpawnerSystem.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 | using ECS.Components;
4 | using System.Collections.Generic;
5 |
6 | namespace ECS.Systems
7 | {
8 | ///
9 | /// System that automatically adds ML-Agent components to all NPCs in the scene.
10 | ///
11 | public class MLAgentSpawnerSystem : SystemBase
12 | {
13 | [Header("ML-Agent Configuration")]
14 | [Tooltip("Whether to use the ML-Agent for decision making")]
15 | public bool enableAgent = true;
16 |
17 | [Tooltip("Decision making interval in seconds")]
18 | public float decisionInterval = 0.5f;
19 |
20 | [Tooltip("Add randomness to decisions based on curiosity")]
21 | public bool useRandomness = true;
22 |
23 | protected override bool CheckDependencies()
24 | {
25 | return IsSystemReady();
26 | }
27 |
28 | protected override void Initialize()
29 | {
30 | if (CheckDependencies())
31 | {
32 | base.Initialize();
33 |
34 | // Find all NPCs in the scene and add ML-Agent components to them
35 | AddMLAgentComponentsToAllNPCs();
36 | }
37 | else
38 | {
39 | Debug.LogError("MLAgentSpawnerSystem initialization failed: NPCSystem not found");
40 | enabled = false;
41 | }
42 | }
43 |
44 | private void AddMLAgentComponentsToAllNPCs()
45 | {
46 | // Find all NPCs in the scene
47 | var npcComponents = FindObjectsOfType();
48 | int count = 0;
49 |
50 | foreach (var npc in npcComponents)
51 | {
52 | // Check if the NPC already has ML-Agent components
53 | if (npc.GetComponent() == null)
54 | {
55 | // Add MLAgentComponent
56 | var mlAgentComponent = npc.gameObject.AddComponent();
57 | mlAgentComponent.isActive = enableAgent;
58 |
59 | // Add NPCAgent
60 | var npcAgent = npc.gameObject.AddComponent();
61 |
62 | // Configure NPCAgent
63 | if (npcAgent != null)
64 | {
65 | // Set decision interval using reflection since it's private
66 | var field = npcAgent.GetType().GetField("decisionInterval",
67 | System.Reflection.BindingFlags.Instance |
68 | System.Reflection.BindingFlags.NonPublic);
69 |
70 | if (field != null)
71 | {
72 | field.SetValue(npcAgent, decisionInterval);
73 | }
74 | }
75 |
76 | count++;
77 | }
78 | }
79 |
80 | Debug.Log($"[MLAgentSpawnerSystem] Added ML-Agent components to {count} NPCs");
81 | }
82 |
83 | public override void UpdateSystem()
84 | {
85 | if (!isInitialized)
86 | {
87 | if (CheckDependencies())
88 | {
89 | Initialize();
90 | }
91 | return;
92 | }
93 |
94 | // Check for new NPCs periodically and add ML-Agent components to them
95 | var npcComponents = FindObjectsOfType();
96 | int count = 0;
97 |
98 | foreach (var npc in npcComponents)
99 | {
100 | // Check if the NPC already has ML-Agent components
101 | if (npc.GetComponent() == null)
102 | {
103 | // Add MLAgentComponent
104 | var mlAgentComponent = npc.gameObject.AddComponent();
105 | mlAgentComponent.isActive = enableAgent;
106 |
107 | // Add NPCAgent
108 | var npcAgent = npc.gameObject.AddComponent();
109 |
110 | // Configure NPCAgent
111 | if (npcAgent != null)
112 | {
113 | // Set decision interval using reflection since it's private
114 | var field = npcAgent.GetType().GetField("decisionInterval",
115 | System.Reflection.BindingFlags.Instance |
116 | System.Reflection.BindingFlags.NonPublic);
117 |
118 | if (field != null)
119 | {
120 | field.SetValue(npcAgent, decisionInterval);
121 | }
122 | }
123 |
124 | count++;
125 | }
126 | }
127 |
128 | if (count > 0)
129 | {
130 | Debug.Log($"[MLAgentSpawnerSystem] Added ML-Agent components to {count} new NPCs");
131 | }
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/SpawnerSystem.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 | using ECS.Components;
4 | using System.Collections.Generic;
5 |
6 | namespace ECS.Systems
7 | {
8 | public class SpawnerSystem : SystemBase
9 | {
10 | [Header("Spawn Settings")]
11 | [SerializeField] private int initialNPCCount = 10;
12 | [SerializeField] private float spawnRadius = 20f;
13 | [SerializeField] private GameObject npcPrefab; // Optional: can be used for visual representation
14 |
15 | [Header("NPC Generation")]
16 | [SerializeField] private Vector2 speedRange = new Vector2(3f, 7f);
17 | [SerializeField] private Vector2 rotationSpeedRange = new Vector2(90f, 180f);
18 | [SerializeField] private Vector2 interactionRangeRange = new Vector2(1f, 3f);
19 |
20 | private ResourceSystem resourceSystem;
21 | private List possibleNames = new List
22 | {
23 | "Alex", "Blake", "Charlie", "Dana", "Eden", "Frankie", "Gray", "Harper",
24 | "Indigo", "Jordan", "Kennedy", "Logan", "Morgan", "Noah", "Parker", "Quinn",
25 | "Riley", "Sage", "Taylor", "Unity", "Val", "Winter", "Xen", "Yuri", "Zen"
26 | };
27 |
28 | protected override bool CheckDependencies()
29 | {
30 | return IsSystemReady();
31 | }
32 |
33 | protected override void Initialize()
34 | {
35 | resourceSystem = GetSystem();
36 |
37 | if (resourceSystem != null)
38 | {
39 | // Spawn initial NPCs
40 | for (int i = 0; i < initialNPCCount; i++)
41 | {
42 | SpawnNPC();
43 | }
44 |
45 | Debug.Log($"Spawned {initialNPCCount} NPCs");
46 | base.Initialize();
47 | }
48 | else
49 | {
50 | Debug.LogError("SpawnerSystem initialization failed: ResourceSystem not found");
51 | enabled = false;
52 | }
53 | }
54 |
55 | public NPCComponent SpawnNPC()
56 | {
57 | // Create GameObject (either from prefab or new)
58 | GameObject npcObject;
59 | if (npcPrefab != null)
60 | {
61 | npcObject = GameObject.Instantiate(npcPrefab);
62 | }
63 | else
64 | {
65 | npcObject = new GameObject("NPC");
66 | // Add basic visual representation
67 | var renderer = npcObject.AddComponent();
68 | var filter = npcObject.AddComponent();
69 | filter.mesh = Resources.GetBuiltinResource("Capsule.fbx");
70 | }
71 |
72 | // Set random position
73 | Vector2 randomCircle = Random.insideUnitCircle * spawnRadius;
74 | npcObject.transform.position = new Vector3(randomCircle.x, 0, randomCircle.y);
75 |
76 | // Add required components
77 | var entity = npcObject.AddComponent();
78 | var npc = npcObject.AddComponent();
79 |
80 | // Configure NPC
81 | npc.npcName = GetRandomName();
82 |
83 | // Set movement properties
84 | npc.moveSpeed = Random.Range(speedRange.x, speedRange.y);
85 | npc.rotationSpeed = Random.Range(rotationSpeedRange.x, rotationSpeedRange.y);
86 | npc.interactionRange = Random.Range(interactionRangeRange.x, interactionRangeRange.y);
87 |
88 | // Randomize personality
89 | npc.personality.sociability = Random.value;
90 | npc.personality.bravery = Random.value;
91 | npc.personality.curiosity = Random.value;
92 | npc.personality.diligence = Random.value;
93 |
94 | // Initialize needs with random values
95 | npc.needs.hunger = Random.Range(0f, 0.3f);
96 | npc.needs.thirst = Random.Range(0f, 0.3f);
97 | npc.needs.energy = Random.Range(0f, 0.3f);
98 | npc.needs.social = Random.Range(0f, 0.3f);
99 |
100 | return npc;
101 | }
102 |
103 | private string GetRandomName()
104 | {
105 | if (possibleNames.Count == 0)
106 | {
107 | return "NPC_" + Random.Range(1000, 9999);
108 | }
109 |
110 | int index = Random.Range(0, possibleNames.Count);
111 | string name = possibleNames[index];
112 | possibleNames.RemoveAt(index); // Ensure unique names
113 | return name;
114 | }
115 |
116 | // Helper method to spawn an NPC at a specific position
117 | public NPCComponent SpawnNPCAt(Vector3 position)
118 | {
119 | var npc = SpawnNPC();
120 | npc.transform.position = position;
121 | return npc;
122 | }
123 |
124 | // Helper method to spawn a group of NPCs
125 | public void SpawnNPCGroup(int count, Vector3 centerPosition, float groupRadius)
126 | {
127 | for (int i = 0; i < count; i++)
128 | {
129 | Vector2 randomOffset = Random.insideUnitCircle * groupRadius;
130 | Vector3 position = centerPosition + new Vector3(randomOffset.x, 0, randomOffset.y);
131 | SpawnNPCAt(position);
132 | }
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/SystemBase.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System;
3 | using System.Collections.Generic;
4 | using ECS.Core.Messaging;
5 |
6 | namespace ECS.Core
7 | {
8 | public abstract class SystemBase : MonoBehaviour
9 | {
10 | protected WorldManager worldManager;
11 | protected HashSet registeredEntities = new HashSet();
12 | protected bool isInitialized = false;
13 |
14 | // Protected access to message bus
15 | protected MessageBus MessageBus => worldManager?.MessageBus;
16 |
17 | // Helper methods for message handling
18 | protected void PublishMessage(T message) where T : Messaging.Message
19 | {
20 | MessageBus?.Publish(message);
21 | }
22 |
23 | protected void SubscribeToMessage(Action handler) where T : Messaging.Message
24 | {
25 | MessageBus?.Subscribe(handler);
26 | }
27 |
28 | protected void UnsubscribeFromMessage(Action handler) where T : Messaging.Message
29 | {
30 | MessageBus?.Unsubscribe(handler);
31 | }
32 |
33 | protected virtual void Awake()
34 | {
35 | // Disable the system initially
36 | enabled = false;
37 |
38 | // Find or create world manager
39 | worldManager = UnityEngine.Object.FindFirstObjectByType(FindObjectsInactive.Include);
40 | if (worldManager == null)
41 | {
42 | var go = new GameObject("World Manager");
43 | worldManager = go.AddComponent();
44 | Debug.Log($"[{GetType().Name}] Created WorldManager automatically");
45 | }
46 |
47 | Debug.Log($"[{GetType().Name}] Awake completed");
48 | }
49 |
50 | protected virtual void Start()
51 | {
52 | // Register with world manager
53 | if (worldManager != null)
54 | {
55 | worldManager.RegisterSystem(this);
56 | Debug.Log($"[{GetType().Name}] Registered with WorldManager");
57 | }
58 | }
59 |
60 | protected virtual void OnEnable()
61 | {
62 | if (!isInitialized && worldManager != null)
63 | {
64 | Debug.Log($"[{GetType().Name}] OnEnable - Checking dependencies");
65 | if (CheckDependencies())
66 | {
67 | Debug.Log($"[{GetType().Name}] Dependencies satisfied, initializing");
68 | Initialize();
69 | }
70 | else
71 | {
72 | Debug.Log($"[{GetType().Name}] Dependencies not ready, disabling");
73 | enabled = false;
74 | }
75 | }
76 | }
77 |
78 | protected virtual void OnDisable()
79 | {
80 | Debug.Log($"[{GetType().Name}] Disabled");
81 | }
82 |
83 | protected virtual void OnDestroy()
84 | {
85 | if (worldManager != null)
86 | {
87 | // Automatically unsubscribe from all messages when system is destroyed
88 | if (MessageBus != null)
89 | {
90 | MessageBus.ClearSubscriptions();
91 | }
92 |
93 | worldManager.UnregisterSystem(this);
94 | Debug.Log($"[{GetType().Name}] Unregistered from WorldManager");
95 | }
96 | }
97 |
98 | // Override this to check if required systems are ready
99 | protected virtual bool CheckDependencies()
100 | {
101 | return true;
102 | }
103 |
104 | // Override this to perform initialization
105 | protected virtual void Initialize()
106 | {
107 | isInitialized = true;
108 |
109 | // Publish initialization message
110 | PublishMessage(new SystemInitializedMessage(this));
111 |
112 | Debug.Log($"[{GetType().Name}] Initialized");
113 | }
114 |
115 | public virtual void RegisterEntity(Entity entity)
116 | {
117 | if (entity != null && !registeredEntities.Contains(entity))
118 | {
119 | registeredEntities.Add(entity);
120 | OnEntityRegistered(entity);
121 | Debug.Log($"[{GetType().Name}] Registered entity: {entity.gameObject.name}");
122 | }
123 | }
124 |
125 | public virtual void UnregisterEntity(Entity entity)
126 | {
127 | if (entity != null && registeredEntities.Contains(entity))
128 | {
129 | registeredEntities.Remove(entity);
130 | OnEntityUnregistered(entity);
131 | Debug.Log($"[{GetType().Name}] Unregistered entity: {entity.gameObject.name}");
132 | }
133 | }
134 |
135 | protected virtual void OnEntityRegistered(Entity entity) { }
136 | protected virtual void OnEntityUnregistered(Entity entity) { }
137 |
138 | // Called by WorldManager during Update
139 | public virtual void UpdateSystem()
140 | {
141 | if (!isInitialized)
142 | {
143 | if (CheckDependencies())
144 | {
145 | Debug.Log($"[{GetType().Name}] Late initialization");
146 | Initialize();
147 | enabled = true;
148 | }
149 | else
150 | {
151 | enabled = false;
152 | }
153 | }
154 | }
155 |
156 | // Helper method to get another system
157 | protected T GetSystem() where T : SystemBase
158 | {
159 | var system = worldManager?.GetSystem();
160 | if (system == null)
161 | {
162 | Debug.LogWarning($"[{GetType().Name}] Failed to get system of type {typeof(T).Name}");
163 | }
164 | return system;
165 | }
166 |
167 | // Helper method to check if a system exists and is initialized
168 | protected bool IsSystemReady() where T : SystemBase
169 | {
170 | var system = GetSystem();
171 | var isReady = system != null && system.isInitialized;
172 | Debug.Log($"[{GetType().Name}] Checking if {typeof(T).Name} is ready: {isReady}");
173 | return isReady;
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/MLAgentSystem.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 | using ECS.Components;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | namespace ECS.Systems
8 | {
9 | public class MLAgentSystem : SystemBase
10 | {
11 | [Header("ML-Agent Settings")]
12 | [SerializeField] private bool enableTraining = true;
13 | [SerializeField] private float decisionInterval = 0.5f;
14 |
15 | private NPCSystem npcSystem;
16 | private ResourceSystem resourceSystem;
17 | private TerrainSystem terrainSystem;
18 |
19 | private float nextDecisionTime;
20 |
21 | protected override bool CheckDependencies()
22 | {
23 | return IsSystemReady() && IsSystemReady() && IsSystemReady();
24 | }
25 |
26 | protected override void Initialize()
27 | {
28 | npcSystem = GetSystem();
29 | resourceSystem = GetSystem();
30 | terrainSystem = GetSystem();
31 |
32 | if (npcSystem != null && resourceSystem != null && terrainSystem != null)
33 | {
34 | nextDecisionTime = Time.time + decisionInterval;
35 | base.Initialize();
36 | }
37 | else
38 | {
39 | Debug.LogError("MLAgentSystem initialization failed: Required systems not found");
40 | enabled = false;
41 | }
42 | }
43 |
44 | public override void UpdateSystem()
45 | {
46 | if (!isInitialized)
47 | {
48 | if (CheckDependencies())
49 | {
50 | Initialize();
51 | }
52 | return;
53 | }
54 |
55 | float currentTime = Time.time;
56 |
57 | // Process ML-Agent decisions at regular intervals
58 | if (currentTime >= nextDecisionTime)
59 | {
60 | nextDecisionTime = currentTime + decisionInterval;
61 |
62 | // Process ML-Agent decisions for each entity
63 | foreach (var entity in registeredEntities)
64 | {
65 | var mlAgentComponent = entity.GetComponent();
66 | if (mlAgentComponent != null && mlAgentComponent.isActive)
67 | {
68 | ProcessAgentDecision(mlAgentComponent);
69 | }
70 | }
71 | }
72 | }
73 |
74 | private void ProcessAgentDecision(MLAgentComponent mlAgentComponent)
75 | {
76 | // Get the NPC component
77 | var npc = mlAgentComponent.npcComponent;
78 | if (npc == null) return;
79 |
80 | // Get the last action from the ML-Agent
81 | int actionType = mlAgentComponent.lastAction;
82 |
83 | // For the proof of concept, we'll implement a simple decision-making process
84 | // In a more comprehensive implementation, we would interpret the actions more sophisticatedly
85 |
86 | // Example: Discrete actions
87 | // Action: 0 = Idle, 1 = Seek Food, 2 = Seek Water, 3 = Seek Rest, 4 = Seek Social
88 | switch (actionType)
89 | {
90 | case 0: // Idle
91 | npc.SetState(NPCComponent.NPCState.Idle);
92 | break;
93 | case 1: // Seek Food
94 | FindAndSetResourceTarget(npc, ResourceComponent.ResourceType.Food);
95 | break;
96 | case 2: // Seek Water
97 | FindAndSetResourceTarget(npc, ResourceComponent.ResourceType.Water);
98 | break;
99 | case 3: // Seek Rest
100 | FindAndSetResourceTarget(npc, ResourceComponent.ResourceType.RestArea);
101 | break;
102 | case 4: // Seek Social
103 | FindAndSetSocialTarget(npc);
104 | break;
105 | }
106 | }
107 |
108 | private void FindAndSetResourceTarget(NPCComponent npc, ResourceComponent.ResourceType resourceType)
109 | {
110 | if (resourceSystem == null) return;
111 |
112 | var resource = resourceSystem.FindBestResource(resourceType, npc.transform.position);
113 |
114 | if (resource != null && resource.CanBeUsed())
115 | {
116 | npc.SetTarget(resource.transform);
117 | npc.SetState(NPCComponent.NPCState.Moving);
118 | }
119 | else
120 | {
121 | // If no resource found, move to a random point
122 | Vector3 randomPoint = GetRandomPointInRange(npc.transform.position, 10f);
123 | npc.SetTarget(randomPoint);
124 | npc.SetState(NPCComponent.NPCState.Moving);
125 | }
126 | }
127 |
128 | private void FindAndSetSocialTarget(NPCComponent npc)
129 | {
130 | var nearbyNPCs = registeredEntities
131 | .Where(e => e.GetComponent() != null && e != npc.GetEntity())
132 | .Select(e => e.GetComponent())
133 | .Where(other => Vector3.Distance(npc.transform.position, other.transform.position) <= 10f)
134 | .OrderBy(other => Vector3.Distance(npc.transform.position, other.transform.position));
135 |
136 | var target = nearbyNPCs.FirstOrDefault();
137 | if (target != null)
138 | {
139 | npc.SetTarget(target.transform);
140 | npc.SetState(NPCComponent.NPCState.Socializing);
141 | }
142 | else
143 | {
144 | // If no NPC found, move to a random point
145 | Vector3 randomPoint = GetRandomPointInRange(npc.transform.position, 10f);
146 | npc.SetTarget(randomPoint);
147 | npc.SetState(NPCComponent.NPCState.Moving);
148 | }
149 | }
150 |
151 | private Vector3 GetRandomPointInRange(Vector3 center, float range)
152 | {
153 | Vector2 random2D = Random.insideUnitCircle * range;
154 | Vector3 randomPoint = center + new Vector3(random2D.x, 0, random2D.y);
155 |
156 | // Get terrain height at random point
157 | if (terrainSystem != null)
158 | {
159 | randomPoint.y = terrainSystem.GetHeightAt(randomPoint);
160 | }
161 |
162 | return randomPoint;
163 | }
164 |
165 | public override void RegisterEntity(Entity entity)
166 | {
167 | if (entity.HasComponent())
168 | {
169 | base.RegisterEntity(entity);
170 | }
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Network Agents
2 |
3 | A Unity-based simulation featuring autonomous agents in a procedurally generated world. The project implements a custom Entity Component System (ECS) architecture to manage complex agent behaviors and world interactions.
4 |
5 | ## Architecture
6 |
7 | ### Entity Component System (ECS)
8 |
9 | The project uses a custom ECS implementation with three main pillars:
10 |
11 | - **WorldManager**: Core orchestrator that manages systems and entities
12 | - **Entities**: Game objects that contain components
13 | - **Components**: Data containers that define entity properties
14 | - **Systems**: Logic processors that operate on entities with specific components
15 |
16 | ### Core Systems
17 |
18 | #### Messaging System
19 | - Centralized message bus for system communication
20 | - Type-safe message publishing and subscription
21 | - Priority-based message processing (Low, Normal, High, Critical)
22 | - Automatic message queue management
23 | - Built-in message types:
24 | - SystemInitializedMessage: Sent when systems initialize
25 | - TimeChangedMessage: Sent on day/night cycle changes
26 | - ResourceStateChangedMessage: Sent when resources update
27 | - NPCNeedsChangedMessage: Sent when NPC needs change
28 | - TerrainChunkGeneratedMessage: Sent when terrain generates
29 |
30 | #### Terrain System
31 | - Procedural terrain generation using multiple noise layers
32 | - Seamless chunk-based world loading
33 | - Multiple biomes (Plains, Forest, Mountains, Desert)
34 | - Smooth transitions between chunks and biomes
35 | - Dynamic LOD and chunk management based on viewer position
36 |
37 | #### NPC System
38 | NPCs are autonomous agents with:
39 | - **Needs**: Hunger, Thirst, Energy, Social
40 | - **Personality Traits**:
41 | - Sociability: Influences desire for social interaction
42 | - Bravery: Affects risk-taking behavior
43 | - Curiosity: Drives exploration
44 | - Diligence: Impacts work ethic and task focus
45 | - **States**:
46 | - Movement: Idle, Moving
47 | - Activities: Working, Resting, Eating, Drinking
48 | - Social: Interacting, Socializing
49 | - **Behaviors**:
50 | - Dynamic decision-making based on needs and personality
51 | - Pathfinding and terrain-aware movement
52 | - Resource seeking and consumption
53 | - Social interaction with other NPCs
54 |
55 | #### Spawner System
56 | - NPC Generation:
57 | - Configurable initial population
58 | - Random name assignment
59 | - Customizable spawn radius and positioning
60 | - Group spawning capabilities
61 | - Initialization:
62 | - Randomized movement properties (speed, rotation, interaction range)
63 | - Unique personality trait generation
64 | - Initial needs randomization
65 | - Optional visual representation through prefabs
66 |
67 | #### Resource System
68 | - Resource Types:
69 | - Food: Consumable for hunger needs
70 | - Water: Consumable for thirst needs
71 | - RestArea: Used for energy recovery
72 | - WorkArea: Designated work locations
73 | - Resource Properties:
74 | - Quantity tracking
75 | - Consumption rates
76 | - Quality multipliers
77 | - Automatic replenishment
78 | - Infinite/finite resources
79 | - Resource Management:
80 | - Usage tracking
81 | - Depletion mechanics
82 | - Replenishment delays
83 | - Visual feedback through Gizmos
84 |
85 | #### Time System
86 | - Configurable day/night cycle:
87 | - Customizable day length
88 | - Dawn, Day, Dusk, Night periods
89 | - Transition periods (dawn/dusk)
90 | - Time Management:
91 | - Real-time to game-time conversion
92 | - Day counting and period tracking
93 | - Progress tracking within each day
94 | - Environmental Impact:
95 | - Influences NPC behavior patterns
96 | - Affects resource availability
97 | - Modifies terrain visualization
98 |
99 | ## Technical Features
100 |
101 | ### Terrain Generation
102 | - Uses FastNoiseLite for coherent noise generation
103 | - Multiple noise layers for varied terrain:
104 | - Base terrain layer
105 | - Biome variation layer
106 | - Detail noise layer
107 | - Smooth chunk transitions using edge blending
108 | - Custom terrain shader for biome visualization
109 |
110 | ### NPC AI
111 | - Needs-based decision making
112 | - Personality-influenced behavior
113 | - Dynamic target selection
114 | - Social interaction system
115 | - Resource seeking and consumption
116 | - Terrain-aware movement
117 |
118 | ### Performance Optimization
119 | - Chunk-based world loading
120 | - Entity pooling
121 | - Efficient component lookup
122 | - Dependency-aware system initialization
123 |
124 | ## Project Structure
125 |
126 | ```
127 | Assets/
128 | ├── Scripts/
129 | │ └── ECS/
130 | │ ├── Core/
131 | │ │ ├── WorldManager.cs # Central ECS orchestrator
132 | │ │ ├── Entity.cs # Base entity class
133 | │ │ ├── ComponentBase.cs # Base component class
134 | │ │ ├── SystemBase.cs # Base system class
135 | │ │ └── Messaging/ # Message-based communication
136 | │ │ ├── Message.cs # Base message class
137 | │ │ ├── MessageBus.cs # Message routing and handling
138 | │ │ └── SystemMessages.cs # Built-in message types
139 | │ ├── Components/
140 | │ │ ├── NPCComponent.cs # NPC properties and state
141 | │ │ ├── ResourceComponent.cs # Resource properties
142 | │ │ ├── TerrainDataComponent.cs # Terrain chunk data
143 | │ │ ├── TimeComponent.cs # Time management
144 | │ │ └── VoxelData.cs # Voxel-based data structures
145 | │ └── Systems/
146 | │ ├── NPCSystem.cs # NPC behavior management
147 | │ ├── ResourceSystem.cs # Resource management
148 | │ ├── TerrainSystem.cs # Terrain generation and management
149 | │ ├── TimeSystem.cs # Time simulation
150 | │ └── SpawnerSystem.cs # Entity spawning
151 | ```
152 |
153 | ## Dependencies
154 |
155 | - Unity Universal Render Pipeline (URP)
156 | - Custom TerrainShader for biome visualization
157 | - FastNoiseLite for procedural generation
158 |
159 | ## Implementation Details
160 |
161 | ### Entity Management
162 | - Automatic component registration
163 | - System dependency resolution
164 | - Event-based component updates
165 | - Efficient entity querying
166 | - Message-based system communication:
167 | - Decoupled system interactions
168 | - Priority-based message processing
169 | - Automatic subscription management
170 | - Type-safe message handling
171 |
172 | ### Terrain Generation
173 | - Multi-threaded chunk generation
174 | - Seamless chunk stitching
175 | - Biome blending
176 | - Height-based biome distribution
177 |
178 | ### NPC Behavior
179 | - State machine-based behavior system
180 | - Need-based decision making
181 | - Dynamic target selection
182 | - Social interaction mechanics
183 | - Resource consumption logic
184 |
185 | ### Resource Management
186 | - Sophisticated resource type system with multiple categories
187 | - Dynamic usage tracking and state management
188 | - Configurable regeneration mechanics:
189 | - Customizable replenishment rates
190 | - Delayed regeneration options
191 | - Quality-based consumption effects
192 | - Proximity-based discovery and interaction
193 | - Visual debugging through Unity Gizmos
194 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Components/TerrainDataComponent.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 |
4 | namespace ECS.Components
5 | {
6 | public class TerrainDataComponent : ComponentBase
7 | {
8 | public enum BiomeType
9 | {
10 | Plains,
11 | Forest,
12 | Mountains,
13 | Desert
14 | }
15 |
16 | [Header("Terrain Data")]
17 | public float[,] heightData;
18 | public BiomeType[,] biomeData;
19 | public float maxHeight = 100f;
20 | public float minHeight = -50f;
21 |
22 | [Header("Generation Parameters")]
23 | public float noiseScale = 50f;
24 | public int octaves = 4;
25 | public float persistence = 0.5f;
26 | public float lacunarity = 2f;
27 | public Vector2 offset;
28 |
29 | [Header("Terrain Size")]
30 | public int terrainSize = 256;
31 | public float terrainScale = 1f;
32 |
33 | private MeshFilter meshFilter;
34 | private MeshRenderer meshRenderer;
35 | private MeshCollider meshCollider;
36 | private Material terrainMaterial;
37 |
38 | public override void Initialize()
39 | {
40 | base.Initialize();
41 |
42 | // Ensure we have all required mesh components
43 | meshFilter = GetComponent();
44 | if (meshFilter == null)
45 | {
46 | meshFilter = gameObject.AddComponent();
47 | Debug.Log($"[{gameObject.name}] Added MeshFilter");
48 | }
49 |
50 | meshRenderer = GetComponent();
51 | if (meshRenderer == null)
52 | {
53 | meshRenderer = gameObject.AddComponent();
54 | Debug.Log($"[{gameObject.name}] Added MeshRenderer");
55 | }
56 |
57 | meshCollider = GetComponent();
58 | if (meshCollider == null)
59 | {
60 | meshCollider = gameObject.AddComponent();
61 | Debug.Log($"[{gameObject.name}] Added MeshCollider");
62 | }
63 |
64 | // Create default material if none assigned
65 | if (meshRenderer.sharedMaterial == null)
66 | {
67 | if (terrainMaterial == null)
68 | {
69 | terrainMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"))
70 | {
71 | color = Color.green
72 | };
73 | }
74 | meshRenderer.sharedMaterial = terrainMaterial;
75 | Debug.Log($"[{gameObject.name}] Assigned default material");
76 | }
77 |
78 | // Initialize arrays with default size
79 | InitializeArrays(terrainSize);
80 | }
81 |
82 | public void InitializeArrays(int size)
83 | {
84 | heightData = new float[size, size];
85 | biomeData = new BiomeType[size, size];
86 |
87 | Debug.Log($"[{gameObject.name}] Initialized arrays with size {size}");
88 | }
89 |
90 | public float GetHeightAt(Vector2 localPosition)
91 | {
92 | if (heightData == null) return 0f;
93 |
94 | int x = Mathf.Clamp(Mathf.FloorToInt(localPosition.x), 0, heightData.GetLength(0) - 1);
95 | int z = Mathf.Clamp(Mathf.FloorToInt(localPosition.y), 0, heightData.GetLength(1) - 1);
96 |
97 | return heightData[x, z];
98 | }
99 |
100 | public BiomeType GetBiomeAt(Vector2 localPosition)
101 | {
102 | if (biomeData == null) return BiomeType.Plains;
103 |
104 | int x = Mathf.Clamp(Mathf.FloorToInt(localPosition.x), 0, biomeData.GetLength(0) - 1);
105 | int z = Mathf.Clamp(Mathf.FloorToInt(localPosition.y), 0, biomeData.GetLength(1) - 1);
106 |
107 | return biomeData[x, z];
108 | }
109 |
110 | public void UpdateMesh()
111 | {
112 | if (heightData == null || meshFilter == null) return;
113 |
114 | int size = heightData.GetLength(0);
115 | Vector3[] vertices = new Vector3[size * size];
116 | int[] triangles = new int[(size - 1) * (size - 1) * 6];
117 | Vector2[] uvs = new Vector2[size * size];
118 | Vector3[] normals = new Vector3[size * size];
119 | Color[] colors = new Color[size * size];
120 |
121 | // Generate vertices and UVs
122 | for (int z = 0; z < size; z++)
123 | {
124 | for (int x = 0; x < size; x++)
125 | {
126 | int index = z * size + x;
127 | float height = heightData[x, z];
128 |
129 | vertices[index] = new Vector3(x * terrainScale, height, z * terrainScale);
130 | uvs[index] = new Vector2((float)x / size, (float)z / size);
131 | normals[index] = Vector3.up; // Will be recalculated later
132 |
133 | // Set vertex color based on biome
134 | colors[index] = GetBiomeColor(biomeData[x, z]);
135 | }
136 | }
137 |
138 | // Generate triangles
139 | int triangleIndex = 0;
140 | for (int z = 0; z < size - 1; z++)
141 | {
142 | for (int x = 0; x < size - 1; x++)
143 | {
144 | int vertexIndex = z * size + x;
145 |
146 | // First triangle
147 | triangles[triangleIndex] = vertexIndex;
148 | triangles[triangleIndex + 1] = vertexIndex + size;
149 | triangles[triangleIndex + 2] = vertexIndex + 1;
150 |
151 | // Second triangle
152 | triangles[triangleIndex + 3] = vertexIndex + 1;
153 | triangles[triangleIndex + 4] = vertexIndex + size;
154 | triangles[triangleIndex + 5] = vertexIndex + size + 1;
155 |
156 | triangleIndex += 6;
157 | }
158 | }
159 |
160 | // Create and assign mesh
161 | Mesh mesh = new Mesh
162 | {
163 | vertices = vertices,
164 | triangles = triangles,
165 | uv = uvs,
166 | normals = normals,
167 | colors = colors
168 | };
169 |
170 | mesh.RecalculateNormals();
171 | mesh.RecalculateBounds();
172 |
173 | meshFilter.sharedMesh = mesh;
174 | if (meshCollider != null)
175 | {
176 | meshCollider.sharedMesh = mesh;
177 | }
178 |
179 | Debug.Log($"[{gameObject.name}] Updated mesh with {vertices.Length} vertices");
180 | }
181 |
182 | private Color GetBiomeColor(BiomeType biome)
183 | {
184 | switch (biome)
185 | {
186 | case BiomeType.Plains:
187 | return new Color(0.4f, 0.8f, 0.4f); // Light green
188 | case BiomeType.Forest:
189 | return new Color(0.2f, 0.6f, 0.2f); // Dark green
190 | case BiomeType.Mountains:
191 | return new Color(0.6f, 0.6f, 0.6f); // Gray
192 | case BiomeType.Desert:
193 | return new Color(0.9f, 0.8f, 0.5f); // Sand color
194 | default:
195 | return Color.white;
196 | }
197 | }
198 |
199 | public void SetMaterial(Material material)
200 | {
201 | if (meshRenderer != null && material != null)
202 | {
203 | terrainMaterial = material;
204 | meshRenderer.sharedMaterial = material;
205 | Debug.Log($"[{gameObject.name}] Updated terrain material");
206 | }
207 | }
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Core/WorldManager.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using ECS.Core.Messaging;
6 |
7 | namespace ECS.Core
8 | {
9 | public class WorldManager : MonoBehaviour
10 | {
11 | private HashSet systems = new HashSet();
12 | private HashSet entities = new HashSet();
13 | private Dictionary> componentEntityMap = new Dictionary>();
14 | private bool isInitializing = false;
15 |
16 | // Message bus for system communication
17 | private MessageBus messageBus;
18 | public MessageBus MessageBus => messageBus;
19 |
20 | private void Awake()
21 | {
22 | // Initialize message bus
23 | messageBus = new MessageBus();
24 | Debug.Log("[WorldManager] MessageBus initialized");
25 | }
26 |
27 | private void Start()
28 | {
29 | // Find all systems in the scene using the newer FindObjectsByType method
30 | var sceneSystems = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None);
31 |
32 | // First register all systems
33 | foreach (var system in sceneSystems)
34 | {
35 | RegisterSystem(system);
36 | }
37 |
38 | Debug.Log($"[WorldManager] Found {sceneSystems.Length} systems in scene");
39 |
40 | // Start initialization process
41 | StartInitialization();
42 | }
43 |
44 | private void StartInitialization()
45 | {
46 | if (isInitializing) return;
47 | isInitializing = true;
48 |
49 | Debug.Log("[WorldManager] Starting system initialization");
50 |
51 | // Try to initialize all systems
52 | bool allInitialized;
53 | int maxAttempts = 10;
54 | int attempt = 0;
55 |
56 | do
57 | {
58 | attempt++;
59 | allInitialized = true;
60 | int initializedThisAttempt = 0;
61 |
62 | foreach (var system in systems)
63 | {
64 | if (!system.enabled)
65 | {
66 | system.enabled = true;
67 | if (!system.enabled) // If system disabled itself due to dependencies
68 | {
69 | allInitialized = false;
70 | Debug.Log($"[WorldManager] System {system.GetType().Name} waiting for dependencies");
71 | }
72 | else
73 | {
74 | initializedThisAttempt++;
75 | Debug.Log($"[WorldManager] System {system.GetType().Name} initialized");
76 | }
77 | }
78 | }
79 |
80 | Debug.Log($"[WorldManager] Initialization attempt {attempt}: Initialized {initializedThisAttempt} systems");
81 |
82 | if (!allInitialized && attempt >= maxAttempts)
83 | {
84 | var uninitialized = systems.Where(s => !s.enabled).Select(s => s.GetType().Name);
85 | Debug.LogError($"[WorldManager] Failed to initialize systems after {maxAttempts} attempts. Uninitialized systems: {string.Join(", ", uninitialized)}");
86 | break;
87 | }
88 |
89 | } while (!allInitialized && attempt < maxAttempts);
90 |
91 | isInitializing = false;
92 | Debug.Log($"[WorldManager] Initialization complete. {systems.Count(s => s.enabled)} systems active");
93 | }
94 |
95 | private void Update()
96 | {
97 | if (!isInitializing)
98 | {
99 | // Process any pending messages before updating systems
100 | messageBus.ProcessMessages();
101 |
102 | // Update all systems in registration order
103 | foreach (var system in systems)
104 | {
105 | if (system.enabled)
106 | {
107 | system.UpdateSystem();
108 | }
109 | }
110 |
111 | // Check if any systems need initialization
112 | bool anyNeedInit = systems.Any(s => !s.enabled);
113 | if (anyNeedInit)
114 | {
115 | StartInitialization();
116 | }
117 |
118 | // Process any messages generated during system updates
119 | messageBus.ProcessMessages();
120 | }
121 | }
122 |
123 | public void RegisterSystem(SystemBase system)
124 | {
125 | if (system != null && !systems.Contains(system))
126 | {
127 | systems.Add(system);
128 | Debug.Log($"[WorldManager] Registered system: {system.GetType().Name}");
129 | }
130 | }
131 |
132 | public void UnregisterSystem(SystemBase system)
133 | {
134 | if (system != null && systems.Contains(system))
135 | {
136 | systems.Remove(system);
137 | Debug.Log($"[WorldManager] Unregistered system: {system.GetType().Name}");
138 | }
139 | }
140 |
141 | public void RegisterEntity(Entity entity)
142 | {
143 | if (entity != null && !entities.Contains(entity))
144 | {
145 | entities.Add(entity);
146 | Debug.Log($"[WorldManager] Registered entity: {entity.gameObject.name}");
147 |
148 | // Register with appropriate systems
149 | foreach (var system in systems)
150 | {
151 | if (system.enabled)
152 | {
153 | system.RegisterEntity(entity);
154 | }
155 | }
156 | }
157 | }
158 |
159 | public void UnregisterEntity(Entity entity)
160 | {
161 | if (entity != null && entities.Contains(entity))
162 | {
163 | entities.Remove(entity);
164 | Debug.Log($"[WorldManager] Unregistered entity: {entity.gameObject.name}");
165 |
166 | // Remove from component-entity map
167 | foreach (var kvp in componentEntityMap)
168 | {
169 | kvp.Value.Remove(entity);
170 | }
171 |
172 | // Unregister from all systems
173 | foreach (var system in systems)
174 | {
175 | system.UnregisterEntity(entity);
176 | }
177 | }
178 | }
179 |
180 | public void OnEntityComponentAdded(Entity entity, ComponentBase component)
181 | {
182 | var componentType = component.GetType();
183 |
184 | // Add to component-entity map
185 | if (!componentEntityMap.ContainsKey(componentType))
186 | {
187 | componentEntityMap[componentType] = new List();
188 | }
189 | if (!componentEntityMap[componentType].Contains(entity))
190 | {
191 | componentEntityMap[componentType].Add(entity);
192 | Debug.Log($"[WorldManager] Added {componentType.Name} to entity: {entity.gameObject.name}");
193 | }
194 |
195 | // Check if entity should be registered with any systems
196 | foreach (var system in systems)
197 | {
198 | if (system.enabled)
199 | {
200 | system.RegisterEntity(entity);
201 | }
202 | }
203 | }
204 |
205 | public void OnEntityComponentRemoved(Entity entity, ComponentBase component)
206 | {
207 | var componentType = component.GetType();
208 |
209 | // Remove from component-entity map
210 | if (componentEntityMap.ContainsKey(componentType))
211 | {
212 | componentEntityMap[componentType].Remove(entity);
213 | Debug.Log($"[WorldManager] Removed {componentType.Name} from entity: {entity.gameObject.name}");
214 | }
215 |
216 | // Check if entity should be unregistered from any systems
217 | foreach (var system in systems)
218 | {
219 | system.UnregisterEntity(entity);
220 | }
221 | }
222 |
223 | public IEnumerable GetEntitiesWithComponent() where T : ComponentBase
224 | {
225 | var componentType = typeof(T);
226 | if (componentEntityMap.ContainsKey(componentType))
227 | {
228 | return componentEntityMap[componentType];
229 | }
230 | return Enumerable.Empty();
231 | }
232 |
233 | public IEnumerable GetAllComponentsOfType() where T : ComponentBase
234 | {
235 | return GetEntitiesWithComponent()
236 | .Select(entity => entity.GetComponent())
237 | .Where(component => component != null);
238 | }
239 |
240 | public IEnumerable GetAllSystems()
241 | {
242 | return systems;
243 | }
244 |
245 | public T GetSystem() where T : SystemBase
246 | {
247 | return systems.OfType().FirstOrDefault();
248 | }
249 |
250 | private void OnDestroy()
251 | {
252 | // Clean up all entities
253 | foreach (var entity in entities.ToList())
254 | {
255 | UnregisterEntity(entity);
256 | }
257 | entities.Clear();
258 | componentEntityMap.Clear();
259 |
260 | // Clean up all systems
261 | foreach (var system in systems.ToList())
262 | {
263 | UnregisterSystem(system);
264 | }
265 | systems.Clear();
266 |
267 | // Clear message bus subscriptions
268 | messageBus.ClearSubscriptions();
269 |
270 | Debug.Log("[WorldManager] Cleanup complete");
271 | }
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/TerrainSystem.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 | using ECS.Components;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | namespace ECS.Systems
8 | {
9 | public class FastNoiseLite
10 | {
11 | public enum NoiseType { OpenSimplex2 }
12 | public enum FractalType { FBm }
13 |
14 | private System.Random random;
15 | private float frequency = 1f;
16 | private int octaves = 1;
17 |
18 | public FastNoiseLite(int seed)
19 | {
20 | random = new System.Random(seed);
21 | }
22 |
23 | public void SetNoiseType(NoiseType type) { }
24 | public void SetFrequency(float freq) { frequency = freq; }
25 | public void SetFractalType(FractalType type) { }
26 | public void SetFractalOctaves(int o) { octaves = o; }
27 |
28 | public float GetNoise(float x, float y)
29 | {
30 | return GetNoise(x, 0, y);
31 | }
32 |
33 | public float GetNoise(float x, float y, float z)
34 | {
35 | x *= frequency;
36 | y *= frequency;
37 | z *= frequency;
38 |
39 | float sum = 0f;
40 | float amplitude = 1f;
41 | float amplitudeSum = 0f;
42 | float freq = 1f;
43 |
44 | for (int i = 0; i < octaves; i++)
45 | {
46 | sum += amplitude * (Mathf.PerlinNoise(x * freq, z * freq) * 2f - 1f);
47 | amplitudeSum += amplitude;
48 | amplitude *= 0.5f;
49 | freq *= 2f;
50 | }
51 |
52 | return sum / amplitudeSum;
53 | }
54 | }
55 |
56 | public class TerrainSystem : SystemBase
57 | {
58 | [Header("Terrain Settings")]
59 | [SerializeField] private Material terrainMaterial;
60 |
61 | [Header("Generation Settings")]
62 | [SerializeField] private float heightMultiplier = 25f;
63 | [SerializeField] private int terrainSize = 256;
64 | [SerializeField] private float terrainScale = 1f;
65 |
66 | private Entity terrainEntity;
67 | private TerrainDataComponent terrainData;
68 | private Material customTerrainMaterial;
69 |
70 | // Noise generators
71 | private FastNoiseLite terrainNoise;
72 | private FastNoiseLite biomeNoise;
73 | private FastNoiseLite detailNoise;
74 |
75 | // Biome transition thresholds
76 | private const float PLAINS_THRESHOLD = 0.3f;
77 | private const float FOREST_THRESHOLD = 0.6f;
78 |
79 | protected override void Initialize()
80 | {
81 | // Initialize noise generators
82 | terrainNoise = new FastNoiseLite(42);
83 | terrainNoise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
84 | terrainNoise.SetFrequency(0.01f); // Adjusted for a single terrain
85 | terrainNoise.SetFractalType(FastNoiseLite.FractalType.FBm);
86 | terrainNoise.SetFractalOctaves(6);
87 |
88 | biomeNoise = new FastNoiseLite(43);
89 | biomeNoise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
90 | biomeNoise.SetFrequency(0.005f); // Wider biome regions
91 | biomeNoise.SetFractalType(FastNoiseLite.FractalType.FBm);
92 | biomeNoise.SetFractalOctaves(3);
93 |
94 | detailNoise = new FastNoiseLite(44);
95 | detailNoise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
96 | detailNoise.SetFrequency(0.02f); // Finer detail scale
97 | detailNoise.SetFractalType(FastNoiseLite.FractalType.FBm);
98 | detailNoise.SetFractalOctaves(3);
99 |
100 | // Create terrain material with custom shader
101 | if (customTerrainMaterial == null)
102 | {
103 | var shader = Shader.Find("Custom/TerrainShader");
104 | if (shader != null)
105 | {
106 | customTerrainMaterial = new Material(shader)
107 | {
108 | enableInstancing = true
109 | };
110 |
111 | // Set biome colors
112 | customTerrainMaterial.SetColor("_PlainsColor", new Color(0.4f, 0.8f, 0.4f));
113 | customTerrainMaterial.SetColor("_ForestColor", new Color(0.2f, 0.6f, 0.2f));
114 | customTerrainMaterial.SetColor("_MountainColor", new Color(0.6f, 0.6f, 0.6f));
115 | customTerrainMaterial.SetColor("_DesertColor", new Color(0.9f, 0.8f, 0.5f));
116 | customTerrainMaterial.SetFloat("_HeightBlend", 0.3f);
117 |
118 | Debug.Log("[TerrainSystem] Created custom terrain material with shader");
119 | }
120 | else
121 | {
122 | Debug.LogError("[TerrainSystem] Failed to find Custom/TerrainShader!");
123 | customTerrainMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
124 | }
125 | }
126 |
127 | base.Initialize();
128 |
129 | // Create a single terrain entity
130 | CreateTerrain();
131 |
132 | Debug.Log("[TerrainSystem] Initialized with single terrain plane");
133 | }
134 |
135 | public override void UpdateSystem()
136 | {
137 | if (!isInitialized) return;
138 |
139 | // No need for continuous updates in the simplified system
140 | // The terrain is generated once and remains static
141 | }
142 |
143 | private void CreateTerrain()
144 | {
145 | // Create terrain game object
146 | var go = new GameObject("Terrain");
147 |
148 | // Add components
149 | terrainEntity = go.AddComponent();
150 | terrainData = go.AddComponent();
151 |
152 | // Initialize terrain data
153 | terrainData.terrainSize = terrainSize;
154 | terrainData.terrainScale = terrainScale;
155 | terrainData.Initialize();
156 | terrainData.SetMaterial(customTerrainMaterial);
157 |
158 | // Center the terrain at origin
159 | float halfSize = (terrainSize * terrainScale) / 2f;
160 | go.transform.position = new Vector3(-halfSize, 0, -halfSize);
161 |
162 | // Generate terrain
163 | GenerateTerrain();
164 |
165 | Debug.Log("[TerrainSystem] Created terrain entity centered at origin");
166 | }
167 |
168 | private void GenerateTerrain()
169 | {
170 | if (terrainData == null) return;
171 |
172 | int size = terrainData.terrainSize;
173 |
174 | // Generate height data
175 | for (int z = 0; z < size; z++)
176 | {
177 | for (int x = 0; x < size; x++)
178 | {
179 | // Calculate normalized coordinates for noise
180 | float normalizedX = (float)x / size;
181 | float normalizedZ = (float)z / size;
182 |
183 | // Generate base terrain
184 | float baseHeight = terrainNoise.GetNoise(x, z);
185 | baseHeight = (baseHeight + 1f) * 0.5f;
186 |
187 | // Generate biome variation
188 | float biomeValue = biomeNoise.GetNoise(x, z);
189 | float biomeHeight = (biomeValue + 1f) * 0.5f;
190 |
191 | // Add fine detail
192 | float detailValue = detailNoise.GetNoise(x * 5f, z * 5f);
193 | float detail = (detailValue + 1f) * 0.5f * 0.15f;
194 |
195 | // Combine heights with weighting
196 | float combinedHeight = baseHeight * 0.6f + biomeHeight * 0.3f + detail * 0.1f;
197 | float finalHeight = Mathf.SmoothStep(0f, 1f, combinedHeight) * heightMultiplier;
198 |
199 | terrainData.heightData[x, z] = finalHeight;
200 |
201 | // Set biome based on height
202 | float normalizedHeight = finalHeight / heightMultiplier;
203 | if (normalizedHeight < PLAINS_THRESHOLD)
204 | {
205 | terrainData.biomeData[x, z] = TerrainDataComponent.BiomeType.Plains;
206 | }
207 | else if (normalizedHeight < FOREST_THRESHOLD)
208 | {
209 | float t = (normalizedHeight - PLAINS_THRESHOLD) / (FOREST_THRESHOLD - PLAINS_THRESHOLD);
210 | terrainData.biomeData[x, z] = t < 0.5f ? TerrainDataComponent.BiomeType.Plains : TerrainDataComponent.BiomeType.Forest;
211 | }
212 | else
213 | {
214 | float t = (normalizedHeight - FOREST_THRESHOLD) / (1f - FOREST_THRESHOLD);
215 | terrainData.biomeData[x, z] = t < 0.5f ? TerrainDataComponent.BiomeType.Forest : TerrainDataComponent.BiomeType.Mountains;
216 | }
217 | }
218 | }
219 |
220 | // Update mesh
221 | terrainData.UpdateMesh();
222 | Debug.Log($"[TerrainSystem] Generated terrain with {size}x{size} vertices");
223 | }
224 |
225 | public float GetHeightAt(Vector3 worldPosition)
226 | {
227 | if (terrainData == null) return 0f;
228 |
229 | // Convert world position to local position, accounting for the centered terrain
230 | Vector3 localPosition = worldPosition - terrainEntity.transform.position;
231 | Vector2 localPos = new Vector2(
232 | localPosition.x / terrainData.terrainScale,
233 | localPosition.z / terrainData.terrainScale
234 | );
235 |
236 | return terrainData.GetHeightAt(localPos);
237 | }
238 |
239 | public TerrainDataComponent.BiomeType GetBiomeAt(Vector3 worldPosition)
240 | {
241 | if (terrainData == null) return TerrainDataComponent.BiomeType.Plains;
242 |
243 | // Convert world position to local position, accounting for the centered terrain
244 | Vector3 localPosition = worldPosition - terrainEntity.transform.position;
245 | Vector2 localPos = new Vector2(
246 | localPosition.x / terrainData.terrainScale,
247 | localPosition.z / terrainData.terrainScale
248 | );
249 |
250 | return terrainData.GetBiomeAt(localPos);
251 | }
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/Assets/Scripts/ECS/Systems/ResourceSystem.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using ECS.Core;
3 | using ECS.Components;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | namespace ECS.Systems
8 | {
9 | public class ResourceSystem : SystemBase
10 | {
11 | [Header("Initial Resource Counts")]
12 | [SerializeField] private int initialFoodSources = 5;
13 | [SerializeField] private int initialWaterSources = 3;
14 | [SerializeField] private int initialRestAreas = 4;
15 | [SerializeField] private float spawnRadius = 20f;
16 |
17 | [Header("Biome Settings")]
18 | [SerializeField] private float forestFoodMultiplier = 2f;
19 | [SerializeField] private float mountainsRestMultiplier = 1.5f;
20 | [SerializeField] private float plainsWaterMultiplier = 1.5f;
21 |
22 | private Dictionary> resourcesByType =
23 | new Dictionary>();
24 |
25 | private TerrainSystem terrainSystem;
26 |
27 | protected override bool CheckDependencies()
28 | {
29 | return IsSystemReady();
30 | }
31 |
32 | protected override void Initialize()
33 | {
34 | // Initialize dictionary for all resource types
35 | foreach (ResourceComponent.ResourceType type in System.Enum.GetValues(typeof(ResourceComponent.ResourceType)))
36 | {
37 | resourcesByType[type] = new List();
38 | }
39 |
40 | terrainSystem = GetSystem();
41 | if (terrainSystem != null)
42 | {
43 | // Spawn initial resources
44 | SpawnInitialResources();
45 | base.Initialize();
46 | }
47 | else
48 | {
49 | Debug.LogError("ResourceSystem initialization failed: TerrainSystem not found");
50 | enabled = false;
51 | }
52 | }
53 |
54 | public override void UpdateSystem()
55 | {
56 | if (!isInitialized)
57 | {
58 | if (CheckDependencies())
59 | {
60 | Initialize();
61 | }
62 | return;
63 | }
64 |
65 | // Update all resources
66 | foreach (var entity in registeredEntities)
67 | {
68 | var resource = entity.GetComponent();
69 | if (resource != null)
70 | {
71 | UpdateResource(resource);
72 | }
73 | }
74 | }
75 |
76 | private void UpdateResource(ResourceComponent resource)
77 | {
78 | if (!resource.isBeingUsed)
79 | {
80 | // Get biome at resource location
81 | var biome = terrainSystem.GetBiomeAt(resource.transform.position);
82 | float replenishMultiplier = GetBiomeReplenishMultiplier(resource.type, biome);
83 |
84 | // Replenish with biome modifier
85 | resource.Replenish(Time.deltaTime * replenishMultiplier);
86 | }
87 | }
88 |
89 | private float GetBiomeReplenishMultiplier(ResourceComponent.ResourceType resourceType, TerrainDataComponent.BiomeType biome)
90 | {
91 | switch (biome)
92 | {
93 | case TerrainDataComponent.BiomeType.Forest when resourceType == ResourceComponent.ResourceType.Food:
94 | return forestFoodMultiplier;
95 | case TerrainDataComponent.BiomeType.Mountains when resourceType == ResourceComponent.ResourceType.RestArea:
96 | return mountainsRestMultiplier;
97 | case TerrainDataComponent.BiomeType.Plains when resourceType == ResourceComponent.ResourceType.Water:
98 | return plainsWaterMultiplier;
99 | default:
100 | return 1f;
101 | }
102 | }
103 |
104 | public override void RegisterEntity(Entity entity)
105 | {
106 | if (entity.HasComponent())
107 | {
108 | base.RegisterEntity(entity);
109 |
110 | // Add to type-specific list
111 | var resource = entity.GetComponent();
112 | resourcesByType[resource.type].Add(resource);
113 | }
114 | }
115 |
116 | public override void UnregisterEntity(Entity entity)
117 | {
118 | if (entity.HasComponent())
119 | {
120 | var resource = entity.GetComponent();
121 | resourcesByType[resource.type].Remove(resource);
122 |
123 | base.UnregisterEntity(entity);
124 | }
125 | }
126 |
127 | public ResourceComponent FindBestResource(ResourceComponent.ResourceType type, Vector3 position, float maxDistance = 50f)
128 | {
129 | if (!resourcesByType.ContainsKey(type))
130 | return null;
131 |
132 | return resourcesByType[type]
133 | .Where(r => r != null && r.CanBeUsed() && Vector3.Distance(position, r.transform.position) <= maxDistance)
134 | .OrderBy(r => Vector3.Distance(position, r.transform.position)) // Prioritize closest
135 | .ThenByDescending(r => r.properties.qualityMultiplier) // Then highest quality
136 | .ThenByDescending(r => r.GetQuantityPercentage()) // Then most available
137 | .FirstOrDefault();
138 | }
139 |
140 | public IEnumerable GetResourcesInRange(ResourceComponent.ResourceType type, Vector3 position, float range)
141 | {
142 | if (!resourcesByType.ContainsKey(type))
143 | return Enumerable.Empty();
144 |
145 | return resourcesByType[type]
146 | .Where(r => r != null && Vector3.Distance(position, r.transform.position) <= range);
147 | }
148 |
149 | public ResourceComponent CreateResource(ResourceComponent.ResourceType type, Vector3 position)
150 | {
151 | GameObject resourceObj = new GameObject($"{type} Resource");
152 | resourceObj.transform.position = position;
153 |
154 | var entity = resourceObj.AddComponent();
155 | var resource = resourceObj.AddComponent();
156 |
157 | resource.type = type;
158 |
159 | // Configure resource properties based on type and biome
160 | var biome = terrainSystem.GetBiomeAt(position);
161 | ConfigureResourceProperties(resource, biome);
162 |
163 | // Adjust position to terrain height
164 | position.y = terrainSystem.GetHeightAt(position);
165 | resourceObj.transform.position = position;
166 |
167 | return resource;
168 | }
169 |
170 | private void ConfigureResourceProperties(ResourceComponent resource, TerrainDataComponent.BiomeType biome)
171 | {
172 | switch (resource.type)
173 | {
174 | case ResourceComponent.ResourceType.Food:
175 | resource.properties.quantity = 100f;
176 | resource.properties.consumptionRate = 10f;
177 | resource.properties.replenishRate = biome == TerrainDataComponent.BiomeType.Forest ? 2f : 1f;
178 | resource.properties.replenishDelay = 30f;
179 | resource.properties.qualityMultiplier = biome == TerrainDataComponent.BiomeType.Forest ? 1.5f : 1f;
180 | break;
181 |
182 | case ResourceComponent.ResourceType.Water:
183 | resource.properties.quantity = 200f;
184 | resource.properties.consumptionRate = 15f;
185 | resource.properties.replenishRate = biome == TerrainDataComponent.BiomeType.Plains ? 3f : 2f;
186 | resource.properties.replenishDelay = 20f;
187 | resource.properties.qualityMultiplier = biome == TerrainDataComponent.BiomeType.Plains ? 1.5f : 1f;
188 | break;
189 |
190 | case ResourceComponent.ResourceType.RestArea:
191 | resource.properties.isInfinite = true;
192 | resource.properties.qualityMultiplier = biome == TerrainDataComponent.BiomeType.Mountains ? 1.5f : 1f;
193 | break;
194 | }
195 | }
196 |
197 | private void SpawnInitialResources()
198 | {
199 | // Create food sources
200 | for (int i = 0; i < initialFoodSources; i++)
201 | {
202 | Vector3 randomPos = GetRandomSpawnPosition(ResourceComponent.ResourceType.Food);
203 | CreateResource(ResourceComponent.ResourceType.Food, randomPos);
204 | }
205 |
206 | // Create water sources
207 | for (int i = 0; i < initialWaterSources; i++)
208 | {
209 | Vector3 randomPos = GetRandomSpawnPosition(ResourceComponent.ResourceType.Water);
210 | CreateResource(ResourceComponent.ResourceType.Water, randomPos);
211 | }
212 |
213 | // Create rest areas
214 | for (int i = 0; i < initialRestAreas; i++)
215 | {
216 | Vector3 randomPos = GetRandomSpawnPosition(ResourceComponent.ResourceType.RestArea);
217 | CreateResource(ResourceComponent.ResourceType.RestArea, randomPos);
218 | }
219 |
220 | Debug.Log($"[ResourceSystem] Spawned initial resources: {initialFoodSources} food, {initialWaterSources} water, {initialRestAreas} rest areas");
221 | }
222 |
223 | private Vector3 GetRandomSpawnPosition(ResourceComponent.ResourceType type)
224 | {
225 | Vector3 position;
226 | TerrainDataComponent.BiomeType biome;
227 | int maxAttempts = 10;
228 | int attempt = 0;
229 |
230 | do
231 | {
232 | position = new Vector3(
233 | Random.Range(-spawnRadius, spawnRadius),
234 | 0,
235 | Random.Range(-spawnRadius, spawnRadius)
236 | );
237 |
238 | biome = terrainSystem.GetBiomeAt(position);
239 | attempt++;
240 |
241 | // Check if this biome is suitable for this resource type
242 | if (IsSuitableBiome(type, biome))
243 | {
244 | position.y = terrainSystem.GetHeightAt(position);
245 | return position;
246 | }
247 |
248 | } while (attempt < maxAttempts);
249 |
250 | // If we couldn't find a suitable biome, just return any position
251 | position.y = terrainSystem.GetHeightAt(position);
252 | return position;
253 | }
254 |
255 | private bool IsSuitableBiome(ResourceComponent.ResourceType type, TerrainDataComponent.BiomeType biome)
256 | {
257 | switch (type)
258 | {
259 | case ResourceComponent.ResourceType.Food:
260 | return biome == TerrainDataComponent.BiomeType.Forest || biome == TerrainDataComponent.BiomeType.Plains;
261 | case ResourceComponent.ResourceType.Water:
262 | return biome == TerrainDataComponent.BiomeType.Plains;
263 | case ResourceComponent.ResourceType.RestArea:
264 | return biome == TerrainDataComponent.BiomeType.Mountains || biome == TerrainDataComponent.BiomeType.Forest;
265 | default:
266 | return true;
267 | }
268 | }
269 | }
270 | }
271 |
--------------------------------------------------------------------------------
/ProjectSettings/InputManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!13 &1
4 | InputManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Axes:
8 | - serializedVersion: 3
9 | m_Name: Horizontal
10 | descriptiveName:
11 | descriptiveNegativeName:
12 | negativeButton: left
13 | positiveButton: right
14 | altNegativeButton: a
15 | altPositiveButton: d
16 | gravity: 3
17 | dead: 0.001
18 | sensitivity: 3
19 | snap: 1
20 | invert: 0
21 | type: 0
22 | axis: 0
23 | joyNum: 0
24 | - serializedVersion: 3
25 | m_Name: Vertical
26 | descriptiveName:
27 | descriptiveNegativeName:
28 | negativeButton: down
29 | positiveButton: up
30 | altNegativeButton: s
31 | altPositiveButton: w
32 | gravity: 3
33 | dead: 0.001
34 | sensitivity: 3
35 | snap: 1
36 | invert: 0
37 | type: 0
38 | axis: 0
39 | joyNum: 0
40 | - serializedVersion: 3
41 | m_Name: Fire1
42 | descriptiveName:
43 | descriptiveNegativeName:
44 | negativeButton:
45 | positiveButton: left ctrl
46 | altNegativeButton:
47 | altPositiveButton: mouse 0
48 | gravity: 1000
49 | dead: 0.001
50 | sensitivity: 1000
51 | snap: 0
52 | invert: 0
53 | type: 0
54 | axis: 0
55 | joyNum: 0
56 | - serializedVersion: 3
57 | m_Name: Fire2
58 | descriptiveName:
59 | descriptiveNegativeName:
60 | negativeButton:
61 | positiveButton: left alt
62 | altNegativeButton:
63 | altPositiveButton: mouse 1
64 | gravity: 1000
65 | dead: 0.001
66 | sensitivity: 1000
67 | snap: 0
68 | invert: 0
69 | type: 0
70 | axis: 0
71 | joyNum: 0
72 | - serializedVersion: 3
73 | m_Name: Fire3
74 | descriptiveName:
75 | descriptiveNegativeName:
76 | negativeButton:
77 | positiveButton: left shift
78 | altNegativeButton:
79 | altPositiveButton: mouse 2
80 | gravity: 1000
81 | dead: 0.001
82 | sensitivity: 1000
83 | snap: 0
84 | invert: 0
85 | type: 0
86 | axis: 0
87 | joyNum: 0
88 | - serializedVersion: 3
89 | m_Name: Jump
90 | descriptiveName:
91 | descriptiveNegativeName:
92 | negativeButton:
93 | positiveButton: space
94 | altNegativeButton:
95 | altPositiveButton:
96 | gravity: 1000
97 | dead: 0.001
98 | sensitivity: 1000
99 | snap: 0
100 | invert: 0
101 | type: 0
102 | axis: 0
103 | joyNum: 0
104 | - serializedVersion: 3
105 | m_Name: Mouse X
106 | descriptiveName:
107 | descriptiveNegativeName:
108 | negativeButton:
109 | positiveButton:
110 | altNegativeButton:
111 | altPositiveButton:
112 | gravity: 0
113 | dead: 0
114 | sensitivity: 0.1
115 | snap: 0
116 | invert: 0
117 | type: 1
118 | axis: 0
119 | joyNum: 0
120 | - serializedVersion: 3
121 | m_Name: Mouse Y
122 | descriptiveName:
123 | descriptiveNegativeName:
124 | negativeButton:
125 | positiveButton:
126 | altNegativeButton:
127 | altPositiveButton:
128 | gravity: 0
129 | dead: 0
130 | sensitivity: 0.1
131 | snap: 0
132 | invert: 0
133 | type: 1
134 | axis: 1
135 | joyNum: 0
136 | - serializedVersion: 3
137 | m_Name: Mouse ScrollWheel
138 | descriptiveName:
139 | descriptiveNegativeName:
140 | negativeButton:
141 | positiveButton:
142 | altNegativeButton:
143 | altPositiveButton:
144 | gravity: 0
145 | dead: 0
146 | sensitivity: 0.1
147 | snap: 0
148 | invert: 0
149 | type: 1
150 | axis: 2
151 | joyNum: 0
152 | - serializedVersion: 3
153 | m_Name: Horizontal
154 | descriptiveName:
155 | descriptiveNegativeName:
156 | negativeButton:
157 | positiveButton:
158 | altNegativeButton:
159 | altPositiveButton:
160 | gravity: 0
161 | dead: 0.19
162 | sensitivity: 1
163 | snap: 0
164 | invert: 0
165 | type: 2
166 | axis: 0
167 | joyNum: 0
168 | - serializedVersion: 3
169 | m_Name: Vertical
170 | descriptiveName:
171 | descriptiveNegativeName:
172 | negativeButton:
173 | positiveButton:
174 | altNegativeButton:
175 | altPositiveButton:
176 | gravity: 0
177 | dead: 0.19
178 | sensitivity: 1
179 | snap: 0
180 | invert: 1
181 | type: 2
182 | axis: 1
183 | joyNum: 0
184 | - serializedVersion: 3
185 | m_Name: Fire1
186 | descriptiveName:
187 | descriptiveNegativeName:
188 | negativeButton:
189 | positiveButton: joystick button 0
190 | altNegativeButton:
191 | altPositiveButton:
192 | gravity: 1000
193 | dead: 0.001
194 | sensitivity: 1000
195 | snap: 0
196 | invert: 0
197 | type: 0
198 | axis: 0
199 | joyNum: 0
200 | - serializedVersion: 3
201 | m_Name: Fire2
202 | descriptiveName:
203 | descriptiveNegativeName:
204 | negativeButton:
205 | positiveButton: joystick button 1
206 | altNegativeButton:
207 | altPositiveButton:
208 | gravity: 1000
209 | dead: 0.001
210 | sensitivity: 1000
211 | snap: 0
212 | invert: 0
213 | type: 0
214 | axis: 0
215 | joyNum: 0
216 | - serializedVersion: 3
217 | m_Name: Fire3
218 | descriptiveName:
219 | descriptiveNegativeName:
220 | negativeButton:
221 | positiveButton: joystick button 2
222 | altNegativeButton:
223 | altPositiveButton:
224 | gravity: 1000
225 | dead: 0.001
226 | sensitivity: 1000
227 | snap: 0
228 | invert: 0
229 | type: 0
230 | axis: 0
231 | joyNum: 0
232 | - serializedVersion: 3
233 | m_Name: Jump
234 | descriptiveName:
235 | descriptiveNegativeName:
236 | negativeButton:
237 | positiveButton: joystick button 3
238 | altNegativeButton:
239 | altPositiveButton:
240 | gravity: 1000
241 | dead: 0.001
242 | sensitivity: 1000
243 | snap: 0
244 | invert: 0
245 | type: 0
246 | axis: 0
247 | joyNum: 0
248 | - serializedVersion: 3
249 | m_Name: Submit
250 | descriptiveName:
251 | descriptiveNegativeName:
252 | negativeButton:
253 | positiveButton: return
254 | altNegativeButton:
255 | altPositiveButton: joystick button 0
256 | gravity: 1000
257 | dead: 0.001
258 | sensitivity: 1000
259 | snap: 0
260 | invert: 0
261 | type: 0
262 | axis: 0
263 | joyNum: 0
264 | - serializedVersion: 3
265 | m_Name: Submit
266 | descriptiveName:
267 | descriptiveNegativeName:
268 | negativeButton:
269 | positiveButton: enter
270 | altNegativeButton:
271 | altPositiveButton: space
272 | gravity: 1000
273 | dead: 0.001
274 | sensitivity: 1000
275 | snap: 0
276 | invert: 0
277 | type: 0
278 | axis: 0
279 | joyNum: 0
280 | - serializedVersion: 3
281 | m_Name: Cancel
282 | descriptiveName:
283 | descriptiveNegativeName:
284 | negativeButton:
285 | positiveButton: escape
286 | altNegativeButton:
287 | altPositiveButton: joystick button 1
288 | gravity: 1000
289 | dead: 0.001
290 | sensitivity: 1000
291 | snap: 0
292 | invert: 0
293 | type: 0
294 | axis: 0
295 | joyNum: 0
296 | - serializedVersion: 3
297 | m_Name: Enable Debug Button 1
298 | descriptiveName:
299 | descriptiveNegativeName:
300 | negativeButton:
301 | positiveButton: left ctrl
302 | altNegativeButton:
303 | altPositiveButton: joystick button 8
304 | gravity: 0
305 | dead: 0
306 | sensitivity: 0
307 | snap: 0
308 | invert: 0
309 | type: 0
310 | axis: 0
311 | joyNum: 0
312 | - serializedVersion: 3
313 | m_Name: Enable Debug Button 2
314 | descriptiveName:
315 | descriptiveNegativeName:
316 | negativeButton:
317 | positiveButton: backspace
318 | altNegativeButton:
319 | altPositiveButton: joystick button 9
320 | gravity: 0
321 | dead: 0
322 | sensitivity: 0
323 | snap: 0
324 | invert: 0
325 | type: 0
326 | axis: 0
327 | joyNum: 0
328 | - serializedVersion: 3
329 | m_Name: Debug Reset
330 | descriptiveName:
331 | descriptiveNegativeName:
332 | negativeButton:
333 | positiveButton: left alt
334 | altNegativeButton:
335 | altPositiveButton: joystick button 1
336 | gravity: 0
337 | dead: 0
338 | sensitivity: 0
339 | snap: 0
340 | invert: 0
341 | type: 0
342 | axis: 0
343 | joyNum: 0
344 | - serializedVersion: 3
345 | m_Name: Debug Next
346 | descriptiveName:
347 | descriptiveNegativeName:
348 | negativeButton:
349 | positiveButton: page down
350 | altNegativeButton:
351 | altPositiveButton: joystick button 5
352 | gravity: 0
353 | dead: 0
354 | sensitivity: 0
355 | snap: 0
356 | invert: 0
357 | type: 0
358 | axis: 0
359 | joyNum: 0
360 | - serializedVersion: 3
361 | m_Name: Debug Previous
362 | descriptiveName:
363 | descriptiveNegativeName:
364 | negativeButton:
365 | positiveButton: page up
366 | altNegativeButton:
367 | altPositiveButton: joystick button 4
368 | gravity: 0
369 | dead: 0
370 | sensitivity: 0
371 | snap: 0
372 | invert: 0
373 | type: 0
374 | axis: 0
375 | joyNum: 0
376 | - serializedVersion: 3
377 | m_Name: Debug Validate
378 | descriptiveName:
379 | descriptiveNegativeName:
380 | negativeButton:
381 | positiveButton: return
382 | altNegativeButton:
383 | altPositiveButton: joystick button 0
384 | gravity: 0
385 | dead: 0
386 | sensitivity: 0
387 | snap: 0
388 | invert: 0
389 | type: 0
390 | axis: 0
391 | joyNum: 0
392 | - serializedVersion: 3
393 | m_Name: Debug Persistent
394 | descriptiveName:
395 | descriptiveNegativeName:
396 | negativeButton:
397 | positiveButton: right shift
398 | altNegativeButton:
399 | altPositiveButton: joystick button 2
400 | gravity: 0
401 | dead: 0
402 | sensitivity: 0
403 | snap: 0
404 | invert: 0
405 | type: 0
406 | axis: 0
407 | joyNum: 0
408 | - serializedVersion: 3
409 | m_Name: Debug Multiplier
410 | descriptiveName:
411 | descriptiveNegativeName:
412 | negativeButton:
413 | positiveButton: left shift
414 | altNegativeButton:
415 | altPositiveButton: joystick button 3
416 | gravity: 0
417 | dead: 0
418 | sensitivity: 0
419 | snap: 0
420 | invert: 0
421 | type: 0
422 | axis: 0
423 | joyNum: 0
424 | - serializedVersion: 3
425 | m_Name: Debug Horizontal
426 | descriptiveName:
427 | descriptiveNegativeName:
428 | negativeButton: left
429 | positiveButton: right
430 | altNegativeButton:
431 | altPositiveButton:
432 | gravity: 1000
433 | dead: 0.001
434 | sensitivity: 1000
435 | snap: 0
436 | invert: 0
437 | type: 0
438 | axis: 0
439 | joyNum: 0
440 | - serializedVersion: 3
441 | m_Name: Debug Vertical
442 | descriptiveName:
443 | descriptiveNegativeName:
444 | negativeButton: down
445 | positiveButton: up
446 | altNegativeButton:
447 | altPositiveButton:
448 | gravity: 1000
449 | dead: 0.001
450 | sensitivity: 1000
451 | snap: 0
452 | invert: 0
453 | type: 0
454 | axis: 0
455 | joyNum: 0
456 | - serializedVersion: 3
457 | m_Name: Debug Vertical
458 | descriptiveName:
459 | descriptiveNegativeName:
460 | negativeButton: down
461 | positiveButton: up
462 | altNegativeButton:
463 | altPositiveButton:
464 | gravity: 1000
465 | dead: 0.001
466 | sensitivity: 1000
467 | snap: 0
468 | invert: 0
469 | type: 2
470 | axis: 6
471 | joyNum: 0
472 | - serializedVersion: 3
473 | m_Name: Debug Horizontal
474 | descriptiveName:
475 | descriptiveNegativeName:
476 | negativeButton: left
477 | positiveButton: right
478 | altNegativeButton:
479 | altPositiveButton:
480 | gravity: 1000
481 | dead: 0.001
482 | sensitivity: 1000
483 | snap: 0
484 | invert: 0
485 | type: 2
486 | axis: 5
487 | joyNum: 0
488 |
--------------------------------------------------------------------------------
/Packages/packages-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "com.unity.ai.navigation": {
4 | "version": "2.0.6",
5 | "depth": 0,
6 | "source": "registry",
7 | "dependencies": {
8 | "com.unity.modules.ai": "1.0.0"
9 | },
10 | "url": "https://packages.unity.com"
11 | },
12 | "com.unity.burst": {
13 | "version": "1.8.19",
14 | "depth": 2,
15 | "source": "registry",
16 | "dependencies": {
17 | "com.unity.mathematics": "1.2.1",
18 | "com.unity.modules.jsonserialize": "1.0.0"
19 | },
20 | "url": "https://packages.unity.com"
21 | },
22 | "com.unity.collab-proxy": {
23 | "version": "2.7.1",
24 | "depth": 0,
25 | "source": "registry",
26 | "dependencies": {},
27 | "url": "https://packages.unity.com"
28 | },
29 | "com.unity.collections": {
30 | "version": "2.5.1",
31 | "depth": 2,
32 | "source": "registry",
33 | "dependencies": {
34 | "com.unity.burst": "1.8.17",
35 | "com.unity.test-framework": "1.4.5",
36 | "com.unity.nuget.mono-cecil": "1.11.4",
37 | "com.unity.test-framework.performance": "3.0.3"
38 | },
39 | "url": "https://packages.unity.com"
40 | },
41 | "com.unity.ext.nunit": {
42 | "version": "2.0.5",
43 | "depth": 1,
44 | "source": "builtin",
45 | "dependencies": {}
46 | },
47 | "com.unity.ide.rider": {
48 | "version": "3.0.35",
49 | "depth": 0,
50 | "source": "registry",
51 | "dependencies": {
52 | "com.unity.ext.nunit": "1.0.6"
53 | },
54 | "url": "https://packages.unity.com"
55 | },
56 | "com.unity.ide.visualstudio": {
57 | "version": "2.0.23",
58 | "depth": 0,
59 | "source": "registry",
60 | "dependencies": {
61 | "com.unity.test-framework": "1.1.9"
62 | },
63 | "url": "https://packages.unity.com"
64 | },
65 | "com.unity.inputsystem": {
66 | "version": "1.14.0",
67 | "depth": 0,
68 | "source": "registry",
69 | "dependencies": {
70 | "com.unity.modules.uielements": "1.0.0"
71 | },
72 | "url": "https://packages.unity.com"
73 | },
74 | "com.unity.mathematics": {
75 | "version": "1.3.2",
76 | "depth": 2,
77 | "source": "registry",
78 | "dependencies": {},
79 | "url": "https://packages.unity.com"
80 | },
81 | "com.unity.multiplayer.center": {
82 | "version": "1.0.0",
83 | "depth": 0,
84 | "source": "builtin",
85 | "dependencies": {
86 | "com.unity.modules.uielements": "1.0.0"
87 | }
88 | },
89 | "com.unity.nuget.mono-cecil": {
90 | "version": "1.11.4",
91 | "depth": 3,
92 | "source": "registry",
93 | "dependencies": {},
94 | "url": "https://packages.unity.com"
95 | },
96 | "com.unity.render-pipelines.core": {
97 | "version": "17.0.4",
98 | "depth": 1,
99 | "source": "builtin",
100 | "dependencies": {
101 | "com.unity.burst": "1.8.14",
102 | "com.unity.mathematics": "1.3.2",
103 | "com.unity.ugui": "2.0.0",
104 | "com.unity.collections": "2.4.3",
105 | "com.unity.modules.physics": "1.0.0",
106 | "com.unity.modules.terrain": "1.0.0",
107 | "com.unity.modules.jsonserialize": "1.0.0",
108 | "com.unity.rendering.light-transport": "1.0.1"
109 | }
110 | },
111 | "com.unity.render-pipelines.universal": {
112 | "version": "17.0.4",
113 | "depth": 0,
114 | "source": "builtin",
115 | "dependencies": {
116 | "com.unity.render-pipelines.core": "17.0.4",
117 | "com.unity.shadergraph": "17.0.4",
118 | "com.unity.render-pipelines.universal-config": "17.0.3"
119 | }
120 | },
121 | "com.unity.render-pipelines.universal-config": {
122 | "version": "17.0.3",
123 | "depth": 1,
124 | "source": "builtin",
125 | "dependencies": {
126 | "com.unity.render-pipelines.core": "17.0.3"
127 | }
128 | },
129 | "com.unity.rendering.light-transport": {
130 | "version": "1.0.1",
131 | "depth": 2,
132 | "source": "builtin",
133 | "dependencies": {
134 | "com.unity.collections": "2.2.0",
135 | "com.unity.mathematics": "1.2.4",
136 | "com.unity.modules.terrain": "1.0.0"
137 | }
138 | },
139 | "com.unity.searcher": {
140 | "version": "4.9.3",
141 | "depth": 2,
142 | "source": "registry",
143 | "dependencies": {},
144 | "url": "https://packages.unity.com"
145 | },
146 | "com.unity.shadergraph": {
147 | "version": "17.0.4",
148 | "depth": 1,
149 | "source": "builtin",
150 | "dependencies": {
151 | "com.unity.render-pipelines.core": "17.0.4",
152 | "com.unity.searcher": "4.9.3"
153 | }
154 | },
155 | "com.unity.test-framework": {
156 | "version": "1.5.1",
157 | "depth": 0,
158 | "source": "builtin",
159 | "dependencies": {
160 | "com.unity.ext.nunit": "2.0.3",
161 | "com.unity.modules.imgui": "1.0.0",
162 | "com.unity.modules.jsonserialize": "1.0.0"
163 | }
164 | },
165 | "com.unity.test-framework.performance": {
166 | "version": "3.0.3",
167 | "depth": 3,
168 | "source": "registry",
169 | "dependencies": {
170 | "com.unity.test-framework": "1.1.31",
171 | "com.unity.modules.jsonserialize": "1.0.0"
172 | },
173 | "url": "https://packages.unity.com"
174 | },
175 | "com.unity.timeline": {
176 | "version": "1.8.7",
177 | "depth": 0,
178 | "source": "registry",
179 | "dependencies": {
180 | "com.unity.modules.audio": "1.0.0",
181 | "com.unity.modules.director": "1.0.0",
182 | "com.unity.modules.animation": "1.0.0",
183 | "com.unity.modules.particlesystem": "1.0.0"
184 | },
185 | "url": "https://packages.unity.com"
186 | },
187 | "com.unity.ugui": {
188 | "version": "2.0.0",
189 | "depth": 0,
190 | "source": "builtin",
191 | "dependencies": {
192 | "com.unity.modules.ui": "1.0.0",
193 | "com.unity.modules.imgui": "1.0.0"
194 | }
195 | },
196 | "com.unity.visualscripting": {
197 | "version": "1.9.6",
198 | "depth": 0,
199 | "source": "registry",
200 | "dependencies": {
201 | "com.unity.ugui": "1.0.0",
202 | "com.unity.modules.jsonserialize": "1.0.0"
203 | },
204 | "url": "https://packages.unity.com"
205 | },
206 | "com.unity.modules.accessibility": {
207 | "version": "1.0.0",
208 | "depth": 0,
209 | "source": "builtin",
210 | "dependencies": {}
211 | },
212 | "com.unity.modules.ai": {
213 | "version": "1.0.0",
214 | "depth": 0,
215 | "source": "builtin",
216 | "dependencies": {}
217 | },
218 | "com.unity.modules.androidjni": {
219 | "version": "1.0.0",
220 | "depth": 0,
221 | "source": "builtin",
222 | "dependencies": {}
223 | },
224 | "com.unity.modules.animation": {
225 | "version": "1.0.0",
226 | "depth": 0,
227 | "source": "builtin",
228 | "dependencies": {}
229 | },
230 | "com.unity.modules.assetbundle": {
231 | "version": "1.0.0",
232 | "depth": 0,
233 | "source": "builtin",
234 | "dependencies": {}
235 | },
236 | "com.unity.modules.audio": {
237 | "version": "1.0.0",
238 | "depth": 0,
239 | "source": "builtin",
240 | "dependencies": {}
241 | },
242 | "com.unity.modules.cloth": {
243 | "version": "1.0.0",
244 | "depth": 0,
245 | "source": "builtin",
246 | "dependencies": {
247 | "com.unity.modules.physics": "1.0.0"
248 | }
249 | },
250 | "com.unity.modules.director": {
251 | "version": "1.0.0",
252 | "depth": 0,
253 | "source": "builtin",
254 | "dependencies": {
255 | "com.unity.modules.audio": "1.0.0",
256 | "com.unity.modules.animation": "1.0.0"
257 | }
258 | },
259 | "com.unity.modules.hierarchycore": {
260 | "version": "1.0.0",
261 | "depth": 1,
262 | "source": "builtin",
263 | "dependencies": {}
264 | },
265 | "com.unity.modules.imageconversion": {
266 | "version": "1.0.0",
267 | "depth": 0,
268 | "source": "builtin",
269 | "dependencies": {}
270 | },
271 | "com.unity.modules.imgui": {
272 | "version": "1.0.0",
273 | "depth": 0,
274 | "source": "builtin",
275 | "dependencies": {}
276 | },
277 | "com.unity.modules.jsonserialize": {
278 | "version": "1.0.0",
279 | "depth": 0,
280 | "source": "builtin",
281 | "dependencies": {}
282 | },
283 | "com.unity.modules.particlesystem": {
284 | "version": "1.0.0",
285 | "depth": 0,
286 | "source": "builtin",
287 | "dependencies": {}
288 | },
289 | "com.unity.modules.physics": {
290 | "version": "1.0.0",
291 | "depth": 0,
292 | "source": "builtin",
293 | "dependencies": {}
294 | },
295 | "com.unity.modules.physics2d": {
296 | "version": "1.0.0",
297 | "depth": 0,
298 | "source": "builtin",
299 | "dependencies": {}
300 | },
301 | "com.unity.modules.screencapture": {
302 | "version": "1.0.0",
303 | "depth": 0,
304 | "source": "builtin",
305 | "dependencies": {
306 | "com.unity.modules.imageconversion": "1.0.0"
307 | }
308 | },
309 | "com.unity.modules.subsystems": {
310 | "version": "1.0.0",
311 | "depth": 1,
312 | "source": "builtin",
313 | "dependencies": {
314 | "com.unity.modules.jsonserialize": "1.0.0"
315 | }
316 | },
317 | "com.unity.modules.terrain": {
318 | "version": "1.0.0",
319 | "depth": 0,
320 | "source": "builtin",
321 | "dependencies": {}
322 | },
323 | "com.unity.modules.terrainphysics": {
324 | "version": "1.0.0",
325 | "depth": 0,
326 | "source": "builtin",
327 | "dependencies": {
328 | "com.unity.modules.physics": "1.0.0",
329 | "com.unity.modules.terrain": "1.0.0"
330 | }
331 | },
332 | "com.unity.modules.tilemap": {
333 | "version": "1.0.0",
334 | "depth": 0,
335 | "source": "builtin",
336 | "dependencies": {
337 | "com.unity.modules.physics2d": "1.0.0"
338 | }
339 | },
340 | "com.unity.modules.ui": {
341 | "version": "1.0.0",
342 | "depth": 0,
343 | "source": "builtin",
344 | "dependencies": {}
345 | },
346 | "com.unity.modules.uielements": {
347 | "version": "1.0.0",
348 | "depth": 0,
349 | "source": "builtin",
350 | "dependencies": {
351 | "com.unity.modules.ui": "1.0.0",
352 | "com.unity.modules.imgui": "1.0.0",
353 | "com.unity.modules.jsonserialize": "1.0.0",
354 | "com.unity.modules.hierarchycore": "1.0.0"
355 | }
356 | },
357 | "com.unity.modules.umbra": {
358 | "version": "1.0.0",
359 | "depth": 0,
360 | "source": "builtin",
361 | "dependencies": {}
362 | },
363 | "com.unity.modules.unityanalytics": {
364 | "version": "1.0.0",
365 | "depth": 0,
366 | "source": "builtin",
367 | "dependencies": {
368 | "com.unity.modules.unitywebrequest": "1.0.0",
369 | "com.unity.modules.jsonserialize": "1.0.0"
370 | }
371 | },
372 | "com.unity.modules.unitywebrequest": {
373 | "version": "1.0.0",
374 | "depth": 0,
375 | "source": "builtin",
376 | "dependencies": {}
377 | },
378 | "com.unity.modules.unitywebrequestassetbundle": {
379 | "version": "1.0.0",
380 | "depth": 0,
381 | "source": "builtin",
382 | "dependencies": {
383 | "com.unity.modules.assetbundle": "1.0.0",
384 | "com.unity.modules.unitywebrequest": "1.0.0"
385 | }
386 | },
387 | "com.unity.modules.unitywebrequestaudio": {
388 | "version": "1.0.0",
389 | "depth": 0,
390 | "source": "builtin",
391 | "dependencies": {
392 | "com.unity.modules.unitywebrequest": "1.0.0",
393 | "com.unity.modules.audio": "1.0.0"
394 | }
395 | },
396 | "com.unity.modules.unitywebrequesttexture": {
397 | "version": "1.0.0",
398 | "depth": 0,
399 | "source": "builtin",
400 | "dependencies": {
401 | "com.unity.modules.unitywebrequest": "1.0.0",
402 | "com.unity.modules.imageconversion": "1.0.0"
403 | }
404 | },
405 | "com.unity.modules.unitywebrequestwww": {
406 | "version": "1.0.0",
407 | "depth": 0,
408 | "source": "builtin",
409 | "dependencies": {
410 | "com.unity.modules.unitywebrequest": "1.0.0",
411 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0",
412 | "com.unity.modules.unitywebrequestaudio": "1.0.0",
413 | "com.unity.modules.audio": "1.0.0",
414 | "com.unity.modules.assetbundle": "1.0.0",
415 | "com.unity.modules.imageconversion": "1.0.0"
416 | }
417 | },
418 | "com.unity.modules.vehicles": {
419 | "version": "1.0.0",
420 | "depth": 0,
421 | "source": "builtin",
422 | "dependencies": {
423 | "com.unity.modules.physics": "1.0.0"
424 | }
425 | },
426 | "com.unity.modules.video": {
427 | "version": "1.0.0",
428 | "depth": 0,
429 | "source": "builtin",
430 | "dependencies": {
431 | "com.unity.modules.audio": "1.0.0",
432 | "com.unity.modules.ui": "1.0.0",
433 | "com.unity.modules.unitywebrequest": "1.0.0"
434 | }
435 | },
436 | "com.unity.modules.vr": {
437 | "version": "1.0.0",
438 | "depth": 0,
439 | "source": "builtin",
440 | "dependencies": {
441 | "com.unity.modules.jsonserialize": "1.0.0",
442 | "com.unity.modules.physics": "1.0.0",
443 | "com.unity.modules.xr": "1.0.0"
444 | }
445 | },
446 | "com.unity.modules.wind": {
447 | "version": "1.0.0",
448 | "depth": 0,
449 | "source": "builtin",
450 | "dependencies": {}
451 | },
452 | "com.unity.modules.xr": {
453 | "version": "1.0.0",
454 | "depth": 0,
455 | "source": "builtin",
456 | "dependencies": {
457 | "com.unity.modules.physics": "1.0.0",
458 | "com.unity.modules.jsonserialize": "1.0.0",
459 | "com.unity.modules.subsystems": "1.0.0"
460 | }
461 | }
462 | }
463 | }
464 |
--------------------------------------------------------------------------------