From fb515ed1cf56629d826748802f18365e16c214e5 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 24 Oct 2025 13:03:16 -0400 Subject: [PATCH] feat: enemies spawn in spawn zones and wander on a graph --- ...stMonsterObjectAnimController 1.controller | 31 +- .../TestEnemy/Objects/TestMonster.prefab | 289 +++++++++++- Assets/Scenes/CombatTest.unity | 417 +++++++++--------- Assets/Scripts/Units/Enemy.cs | 5 +- .../Scripts/Units/Enemy/EnemyPathfinding.cs | 83 +++- Assets/Scripts/Units/Enemy/EnemySpawn.cs | 78 ++-- 6 files changed, 633 insertions(+), 270 deletions(-) diff --git a/Assets/Enemies/TestEnemy/Models/TestMonster/TestMonsterObjectAnimController 1.controller b/Assets/Enemies/TestEnemy/Models/TestMonster/TestMonsterObjectAnimController 1.controller index cfddbe3..28a0e3d 100644 --- a/Assets/Enemies/TestEnemy/Models/TestMonster/TestMonsterObjectAnimController 1.controller +++ b/Assets/Enemies/TestEnemy/Models/TestMonster/TestMonsterObjectAnimController 1.controller @@ -1,5 +1,31 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: +--- !u!1102 &-7846314796881791032 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: New State + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: [] + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: 0} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: --- !u!1107 &-6638317236673258601 AnimatorStateMachine: serializedVersion: 6 @@ -12,6 +38,9 @@ AnimatorStateMachine: - serializedVersion: 1 m_State: {fileID: 6611013841474026752} m_Position: {x: 520, y: 120, z: 0} + - serializedVersion: 1 + m_State: {fileID: -7846314796881791032} + m_Position: {x: 280, y: 40, z: 0} m_ChildStateMachines: [] m_AnyStateTransitions: [] m_EntryTransitions: [] @@ -21,7 +50,7 @@ AnimatorStateMachine: m_EntryPosition: {x: 50, y: 120, z: 0} m_ExitPosition: {x: 800, y: 120, z: 0} m_ParentStateMachinePosition: {x: 800, y: 20, z: 0} - m_DefaultState: {fileID: 6611013841474026752} + m_DefaultState: {fileID: -7846314796881791032} --- !u!91 &9100000 AnimatorController: m_ObjectHideFlags: 0 diff --git a/Assets/Enemies/TestEnemy/Objects/TestMonster.prefab b/Assets/Enemies/TestEnemy/Objects/TestMonster.prefab index f1c1b4a..5ee0275 100644 --- a/Assets/Enemies/TestEnemy/Objects/TestMonster.prefab +++ b/Assets/Enemies/TestEnemy/Objects/TestMonster.prefab @@ -12,6 +12,13 @@ GameObject: - component: {fileID: 2562293259993124465} - component: {fileID: 8206397622550667234} - component: {fileID: 5956987736849929195} + - component: {fileID: 4447190118606394553} + - component: {fileID: 3375213058463339329} + - component: {fileID: 6881462958115636691} + - component: {fileID: 5075083518210584453} + - component: {fileID: 1077794308846883818} + - component: {fileID: 6620953456884791151} + - component: {fileID: 6778397863327314458} m_Layer: 7 m_Name: TestMonster m_TagString: Untagged @@ -47,7 +54,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Name: m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject - GlobalObjectIdHash: 972023326 + GlobalObjectIdHash: 1434729210 InScenePlacedSourceGlobalObjectIdHash: 0 DeferredDespawnTick: 0 Ownership: 1 @@ -73,6 +80,77 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: Core::Reset.Units.Enemy ShowTopMostFoldoutHeaderGroup: 1 + graphStateAsString: + m_InternalValue: + utf8LengthInBytes: 0 + bytes: + offset0000: + byte0000: 0 + byte0001: 0 + byte0002: 0 + byte0003: 0 + byte0004: 0 + byte0005: 0 + byte0006: 0 + byte0007: 0 + byte0008: 0 + byte0009: 0 + byte0010: 0 + byte0011: 0 + byte0012: 0 + byte0013: 0 + byte0014: 0 + byte0015: 0 + offset0016: + byte0000: 0 + byte0001: 0 + byte0002: 0 + byte0003: 0 + byte0004: 0 + byte0005: 0 + byte0006: 0 + byte0007: 0 + byte0008: 0 + byte0009: 0 + byte0010: 0 + byte0011: 0 + byte0012: 0 + byte0013: 0 + byte0014: 0 + byte0015: 0 + offset0032: + byte0000: 0 + byte0001: 0 + byte0002: 0 + byte0003: 0 + byte0004: 0 + byte0005: 0 + byte0006: 0 + byte0007: 0 + byte0008: 0 + byte0009: 0 + byte0010: 0 + byte0011: 0 + byte0012: 0 + byte0013: 0 + byte0014: 0 + byte0015: 0 + byte0048: 0 + byte0049: 0 + byte0050: 0 + byte0051: 0 + byte0052: 0 + byte0053: 0 + byte0054: 0 + byte0055: 0 + byte0056: 0 + byte0057: 0 + byte0058: 0 + byte0059: 0 + byte0060: 0 + byte0061: 0 + relatedSpawner: {fileID: 0} + testModelAnimator: {fileID: 0} --- !u!114 &5956987736849929195 MonoBehaviour: m_ObjectHideFlags: 0 @@ -85,6 +163,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: b3b4e13d59527d1429a62dde97c6a001, type: 3} m_Name: m_EditorClassIdentifier: Core::Reset.Units.UnitMovementHandler + ShowTopMostFoldoutHeaderGroup: 1 data: directionChangingSoftness: targetValue: 1 @@ -123,30 +202,30 @@ MonoBehaviour: defaultSmoothing: 1 defaultEasing: 2 acceleration: - targetValue: 5 - currentValue: 5 + targetValue: 20 + currentValue: 20 targetSmoothing: 1 targetEasing: 2 currentSmoothing: 1 - defaultValue: 5 + defaultValue: 20 defaultSmoothing: 1 defaultEasing: 2 deacceleration: - targetValue: 5 - currentValue: 5 + targetValue: 10 + currentValue: 10 targetSmoothing: 1 targetEasing: 2 currentSmoothing: 1 - defaultValue: 5 + defaultValue: 10 defaultSmoothing: 1 defaultEasing: 2 moveSpeed: - targetValue: 15 - currentValue: 15 + targetValue: 5 + currentValue: 5 targetSmoothing: 10 targetEasing: 2 currentSmoothing: 10 - defaultValue: 15 + defaultValue: 5 defaultSmoothing: 10 defaultEasing: 2 gravityPower: @@ -204,6 +283,196 @@ MonoBehaviour: defaultSmoothing: 1 defaultEasing: 2 specifiedRotation: {x: 0, y: 0, z: 0} +--- !u!95 &4447190118606394553 +Animator: + serializedVersion: 7 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9098724353270996650} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: 4f5596a1d63365d4cba1b75587fe5939, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 1 + m_LinearVelocityBlending: 0 + m_StabilizeFeet: 0 + m_AnimatePhysics: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorStateOnDisable: 0 + m_WriteDefaultValuesOnDisable: 0 +--- !u!114 &3375213058463339329 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9098724353270996650} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4a7dbb6bbdf4ffb46ab7dd87ba8191e7, type: 3} + m_Name: + m_EditorClassIdentifier: NodeCanvas::NodeCanvas.StateMachines.FSMOwner + _serializedExposedParameters: [] + _boundGraphSerialization: + _boundGraphObjectReferences: [] + _boundGraphSource: + _version: 0 + _category: + _comments: + _translation: {x: 0, y: 0} + _zoomFactor: 1 + _firstActivation: 0 + _enableAction: 0 + _disableAction: 0 + _lockBoundGraphPrefabOverrides: 1 + _preInitializeSubGraphs: 0 + _updateMode: 0 + _graph: {fileID: 11400000, guid: db5b23d2ee7fffd49a42d5a120c50e94, type: 2} + _blackboard: {fileID: 0} +--- !u!114 &6881462958115636691 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9098724353270996650} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b98a6db0b653f764eac834f85857a9dd, type: 3} + m_Name: + m_EditorClassIdentifier: ParadoxNotion::NodeCanvas.Framework.Blackboard + _parentBlackboard: {fileID: 0} + _serializedBlackboard: '{"_variables":{}}' + _objectReferences: [] + _serializedVariables: [] +--- !u!114 &5075083518210584453 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9098724353270996650} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 373b52eb9bf8c40f785bb6947a1aee66, type: 3} + m_Name: + m_EditorClassIdentifier: AstarPathfindingProject::Pathfinding.Seeker + version: 1073741824 + drawGizmos: 1 + detailedGizmos: 0 + startEndModifier: + addPoints: 0 + exactStartPoint: 3 + exactEndPoint: 3 + useRaycasting: 0 + mask: + serializedVersion: 2 + m_Bits: 4294967295 + useGraphRaycasting: 0 + traversableTags: -1 + tagCostMultipliers: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + tagEntryCosts: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + graphMask: + value: -1 +--- !u!114 &1077794308846883818 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9098724353270996650} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1a67969fa2454c8f8b5c84c31c95d890, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Reset.Units.EnemyPathfinding + ShowTopMostFoldoutHeaderGroup: 1 + nextWaypointDistance: 3 + reachedEndOfPath: 0 +--- !u!143 &6620953456884791151 +CharacterController: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9098724353270996650} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Height: 2 + m_Radius: 0.5 + m_SlopeLimit: 45 + m_StepOffset: 0.3 + m_SkinWidth: 0.08 + m_MinMoveDistance: 0.001 + m_Center: {x: 0, y: 1, z: 0} +--- !u!114 &6778397863327314458 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9098724353270996650} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: cb6a34d769a1e4ac7b0b30e433aa443c, type: 3} + m_Name: + m_EditorClassIdentifier: AstarPathfindingProject::Pathfinding.SimpleSmoothModifier + version: 1073741824 + smoothType: 0 + subdivisions: 2 + iterations: 2 + strength: 0.5 + uniformLength: 1 + maxSegmentLength: 2 + bezierTangentLength: 0.4 + offset: 0.2 + factor: 0.1 --- !u!1001 &8807019661255186479 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/Scenes/CombatTest.unity b/Assets/Scenes/CombatTest.unity index ba7e919..0180bd6 100644 --- a/Assets/Scenes/CombatTest.unity +++ b/Assets/Scenes/CombatTest.unity @@ -1444,6 +1444,126 @@ MonoBehaviour: m_EditorClassIdentifier: m_Padding: {x: -8, y: -5, z: -8, w: -5} m_Softness: {x: 0, y: 0} +--- !u!1 &332821854 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 332821856} + - component: {fileID: 332821855} + m_Layer: 0 + m_Name: AstarManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &332821855 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 332821854} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78396926cbbfc4ac3b48fc5fc34a87d1, type: 3} + m_Name: + m_EditorClassIdentifier: AstarPathfindingProject::AstarPath + version: 1073741824 + data: + dataString: UEsDBBQAAAgIAACYn+uPWR/UpwIAAOoFAAALACQAZ3JhcGgwLmpzb24KACAAAAAAAAEAGAAAgD7V3rGdAQCAPtXesZ0BAIA+1d6xnQGFVE1vGjEQ/SvI56ZaaNqE3logpIckqKTKoZvDxJ5lLYy98keARPz3jr0GFiq1EtIub77evJnZdya1a5B7Y6dWijsjkH3tsfjOPvSOxlvcwMLouXzDvc+TFL6OTpB8foKXhvB+DHNmhd5K/k0vVHQuCAxaVsauJmKBI+O8I7gC5ZBM1vgYrQl677FNDtjm51t89nb0xlF7tP/zCporWDUoItujc3/v3W/dNPWRPSJnbpSSLpNgftukJkfQuEAtkIOQQE2l8tG/RrmoPf0ZdIMfqsqhz5QsbMfSkjZtVvbdtIKtwC1bXq+gAh6Itynv/rJe9JO5smZ1u6/aL2IFX0u+/AlbDs539OzC41PaQa9BLeFF4VON+t5MrQlakNHbEEODw8G4k+rQ2ahGvjz6tVzPwND8cza71Ptm7rE59FF8vDyivxy6uTJJ+pwyWjIyjKnQ0th+UD9pYVwuQGjkSPGPsOhuVjbcSOs8mbIIGY2+M5oPCtQcs+4X0UFHei8m2JiLTRLXKEbwI2M1JjgTbFCD8tsZZfTnC3Bm6/A6s9xAPLLMLtv2t3MWkuCjf1GcmWZmfRi2pdV1aZ/3b7+f4xBcbdZ36OqH4JXUHbWj4Z4EHhmt273tirkPmwdbAe+Eedz4YHEMHlI1okMLJrqhpGWK0EGpuMupgcSIGoi/56hvDVRXJZjdG53u7uSZ6C+CFKcXwl6gf9X/VMDVkF8jH365uB4Ul9Vg+BmQV6KCiqUTkprkBjVr9cpTou3Sx140ncv+E9ibWmjSyQoL66l8W5nO5KWuzJxbRP3QZjg0i5aK0KdFTISkNufovdRpL9l7yZThSxTlIVGZhJ1svIXymKVkjXw1PiIlG6UPX8kifLhIWt1XietY/CQZKhodikepcAVNNBU7tvsDUEsDBBQAAAgIAACYn+sYgko/bAAAAHcAAAAJACQAbWV0YS5qc29uCgAgAAAAAAABABgAAIA+1d6xnQEAgD7V3rGdAQCAPtXesZ0Bq1YqSy0qzszPU7JSMNUz0TPRUVBKL0osyCgGChiCOKWZKSB2tFJSoqG5obFBorllskVqsqWZroWRgUmakaVpYmpyWkpaYppSLFB9SWVBql9ibipET0BiSUZaZl5KZl66nntRZoo7yGil2FoAUEsBAi0AFAAACAgAAJif649ZH9SnAgAA6gUAAAsAJAAAAAAAAAAAAAAAAAAAAGdyYXBoMC5qc29uCgAgAAAAAAABABgAAIA+1d6xnQEAgD7V3rGdAQCAPtXesZ0BUEsBAi0AFAAACAgAAJif6xiCSj9sAAAAdwAAAAkAJAAAAAAAAAAAAAAA9AIAAG1ldGEuanNvbgoAIAAAAAAAAQAYAACAPtXesZ0BAIA+1d6xnQEAgD7V3rGdAVBLBQYAAAAAAgACALgAAACrAwAAAAA= + file_cachedStartup: {fileID: 0} + cacheStartup: 0 + showNavGraphs: 1 + showUnwalkableNodes: 1 + debugMode: 0 + graphUpdateDebugMode: 0 + debugFloor: 0 + debugRoof: 1 + manualDebugFloorRoof: 0 + showSearchTree: 0 + unwalkableNodeDebugSize: 0.3 + logPathResults: 1 + maxNearestNodeDistance: 100 + scanOnStartup: 1 + fullGetNearestSearch: 0 + prioritizeGraphs: 0 + prioritizeGraphsLimit: 1 + colorSettings: + _SolidColor: {r: 0.11764706, g: 0.4, b: 0.7882353, a: 0.9} + _UnwalkableNode: {r: 1, g: 0, b: 0, a: 0.5} + _BoundsHandles: {r: 0.29, g: 0.454, b: 0.741, a: 0.9} + _ConnectionLowLerp: {r: 0, g: 1, b: 0, a: 0.5} + _ConnectionHighLerp: {r: 1, g: 0, b: 0, a: 0.5} + _MeshEdgeColor: {r: 0, g: 0, b: 0, a: 0.5} + _AreaColors: [] + tagNames: + - Basic Ground + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 + - 16 + - 17 + - 18 + - 19 + - 20 + - 21 + - 22 + - 23 + - 24 + - 25 + - 26 + - 27 + - 28 + - 29 + - 30 + - 31 + heuristic: 2 + heuristicScale: 1 + threadCount: 1 + maxFrameTime: 1 + batchGraphUpdates: 0 + graphUpdateBatchingInterval: 0.2 + navmeshUpdates: + updateInterval: 0 + euclideanEmbedding: + mode: 0 + seed: 0 + pivotPointRoot: {fileID: 0} + spreadOutCount: 10 + showGraphs: 1 + showGraphsInStandalonePlayer: 0 +--- !u!4 &332821856 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 332821854} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &358889608 PrefabInstance: m_ObjectHideFlags: 0 @@ -2326,6 +2446,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 1814906103} + - target: {fileID: 1750107573202608168, guid: 441325715ff6aa647af490a592c0f659, type: 3} + propertyPath: m_VersionIndex + value: 744 + objectReference: {fileID: 0} - target: {fileID: 4267764818278467938, guid: 441325715ff6aa647af490a592c0f659, type: 3} propertyPath: m_Mesh value: @@ -2386,6 +2510,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 1101427058} + - target: {fileID: 7698775267226572509, guid: 441325715ff6aa647af490a592c0f659, type: 3} + propertyPath: m_VersionIndex + value: 547 + objectReference: {fileID: 0} - target: {fileID: 7858299310152251701, guid: 441325715ff6aa647af490a592c0f659, type: 3} propertyPath: m_Mesh value: @@ -2398,6 +2526,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 2089547447} + - target: {fileID: 8730273893382106019, guid: 441325715ff6aa647af490a592c0f659, type: 3} + propertyPath: m_VersionIndex + value: 1700 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] @@ -2576,6 +2708,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 55045520} + - target: {fileID: 1750107573202608168, guid: 441325715ff6aa647af490a592c0f659, type: 3} + propertyPath: m_VersionIndex + value: 744 + objectReference: {fileID: 0} - target: {fileID: 4267764818278467938, guid: 441325715ff6aa647af490a592c0f659, type: 3} propertyPath: m_Mesh value: @@ -2636,6 +2772,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 1718680066} + - target: {fileID: 7698775267226572509, guid: 441325715ff6aa647af490a592c0f659, type: 3} + propertyPath: m_VersionIndex + value: 547 + objectReference: {fileID: 0} - target: {fileID: 7858299310152251701, guid: 441325715ff6aa647af490a592c0f659, type: 3} propertyPath: m_Mesh value: @@ -2648,6 +2788,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 1139271064} + - target: {fileID: 8730273893382106019, guid: 441325715ff6aa647af490a592c0f659, type: 3} + propertyPath: m_VersionIndex + value: 1700 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] @@ -2669,6 +2813,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 1567360890} + - target: {fileID: 986332541933419534, guid: 64aa98352a8043b489346bd369d455e9, type: 3} + propertyPath: m_VersionIndex + value: 687 + objectReference: {fileID: 0} - target: {fileID: 1340212685143914910, guid: 64aa98352a8043b489346bd369d455e9, type: 3} propertyPath: m_Mesh value: @@ -2681,6 +2829,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 2121365581} + - target: {fileID: 2421113883819843321, guid: 64aa98352a8043b489346bd369d455e9, type: 3} + propertyPath: m_VersionIndex + value: 801 + objectReference: {fileID: 0} - target: {fileID: 2758870566962939460, guid: 64aa98352a8043b489346bd369d455e9, type: 3} propertyPath: m_Mesh value: @@ -2705,10 +2857,18 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 178405908} + - target: {fileID: 6299536975461695514, guid: 64aa98352a8043b489346bd369d455e9, type: 3} + propertyPath: m_VersionIndex + value: 1261 + objectReference: {fileID: 0} - target: {fileID: 6743514157665315753, guid: 64aa98352a8043b489346bd369d455e9, type: 3} propertyPath: m_Mesh value: objectReference: {fileID: 212772171} + - target: {fileID: 6743514157665315753, guid: 64aa98352a8043b489346bd369d455e9, type: 3} + propertyPath: m_VersionIndex + value: 706 + objectReference: {fileID: 0} - target: {fileID: 6809092558047272506, guid: 64aa98352a8043b489346bd369d455e9, type: 3} propertyPath: m_Mesh value: @@ -2765,6 +2925,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 1162239009} + - target: {fileID: 9062635394175851895, guid: 64aa98352a8043b489346bd369d455e9, type: 3} + propertyPath: m_VersionIndex + value: 676 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] @@ -3182,6 +3346,7 @@ GameObject: m_Component: - component: {fileID: 797489998} - component: {fileID: 797489997} + - component: {fileID: 797489999} m_Layer: 0 m_Name: EnemySpawn m_TagString: Untagged @@ -3222,6 +3387,22 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &797489999 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 797489996} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6a634230476dc478b88eceac73b1c8a4, type: 3} + m_Name: + m_EditorClassIdentifier: AstarPathfindingProject::Pathfinding.ProceduralGraphMover + version: 1073741824 + updateDistance: 10 + target: {fileID: 797489998} + graphIndex: 0 --- !u!1 &804831197 GameObject: m_ObjectHideFlags: 0 @@ -4559,6 +4740,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 1232968165} + - target: {fileID: 1086363638099167441, guid: 5b583673431733f4294eb175d9929f97, type: 3} + propertyPath: m_VersionIndex + value: 147 + objectReference: {fileID: 0} - target: {fileID: 1207694693265953541, guid: 5b583673431733f4294eb175d9929f97, type: 3} propertyPath: m_LocalPosition.x value: -43 @@ -4603,6 +4788,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 1010515263} + - target: {fileID: 2742140022625329115, guid: 5b583673431733f4294eb175d9929f97, type: 3} + propertyPath: m_VersionIndex + value: 171 + objectReference: {fileID: 0} - target: {fileID: 3126855805493845587, guid: 5b583673431733f4294eb175d9929f97, type: 3} propertyPath: m_Mesh value: @@ -4623,6 +4812,10 @@ PrefabInstance: propertyPath: m_Mesh value: objectReference: {fileID: 1947664487} + - target: {fileID: 6692872533044386436, guid: 5b583673431733f4294eb175d9929f97, type: 3} + propertyPath: m_VersionIndex + value: 113 + objectReference: {fileID: 0} - target: {fileID: 6873792292218326133, guid: 5b583673431733f4294eb175d9929f97, type: 3} propertyPath: m_Mesh value: @@ -6344,6 +6537,10 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: -55.30239 objectReference: {fileID: 0} + - target: {fileID: 3375213058463339329, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} + propertyPath: _blackboard + value: + objectReference: {fileID: 1668865131} - target: {fileID: 3428415627849171540, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 28.353235 @@ -6410,7 +6607,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 4118401780831850168, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} propertyPath: m_LocalPosition.y - value: -0.0000009536743 + value: 0 objectReference: {fileID: 0} - target: {fileID: 4118401780831850168, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} propertyPath: m_LocalPosition.z @@ -6688,58 +6885,23 @@ PrefabInstance: propertyPath: m_Name value: TestMonster (1) objectReference: {fileID: 0} + - target: {fileID: 9098724353270996650, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] m_AddedComponents: - - targetCorrespondingSourceObject: {fileID: 9098724353270996650, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} - insertIndex: -1 - addedObject: {fileID: 1668865125} - - targetCorrespondingSourceObject: {fileID: 9098724353270996650, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} - insertIndex: -1 - addedObject: {fileID: 1668865132} - - targetCorrespondingSourceObject: {fileID: 9098724353270996650, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} - insertIndex: -1 - addedObject: {fileID: 1668865131} - - targetCorrespondingSourceObject: {fileID: 9098724353270996650, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} - insertIndex: -1 - addedObject: {fileID: 1668865133} - targetCorrespondingSourceObject: {fileID: 8573086128984434046, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} insertIndex: -1 addedObject: {fileID: 1668865126} m_SourcePrefab: {fileID: 100100000, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} ---- !u!1 &1668865123 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 9098724353270996650, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} - m_PrefabInstance: {fileID: 1668865122} - m_PrefabAsset: {fileID: 0} --- !u!1 &1668865124 stripped GameObject: m_CorrespondingSourceObject: {fileID: 8573086128984434046, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} m_PrefabInstance: {fileID: 1668865122} m_PrefabAsset: {fileID: 0} ---- !u!95 &1668865125 -Animator: - serializedVersion: 7 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1668865123} - m_Enabled: 1 - m_Avatar: {fileID: 0} - m_Controller: {fileID: 9100000, guid: 4f5596a1d63365d4cba1b75587fe5939, type: 2} - m_CullingMode: 0 - m_UpdateMode: 0 - m_ApplyRootMotion: 1 - m_LinearVelocityBlending: 0 - m_StabilizeFeet: 0 - m_AnimatePhysics: 0 - m_WarningMessage: - m_HasTransformHierarchy: 1 - m_AllowConstantClipSamplingOptimization: 1 - m_KeepAnimatorStateOnDisable: 0 - m_WriteDefaultValuesOnDisable: 0 --- !u!95 &1668865126 Animator: serializedVersion: 7 @@ -6762,183 +6924,17 @@ Animator: m_AllowConstantClipSamplingOptimization: 1 m_KeepAnimatorStateOnDisable: 0 m_WriteDefaultValuesOnDisable: 0 ---- !u!114 &1668865131 +--- !u!114 &1668865131 stripped MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} + m_CorrespondingSourceObject: {fileID: 6881462958115636691, guid: 7dca717b905799e4cb7f64180d31be25, type: 3} + m_PrefabInstance: {fileID: 1668865122} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1668865123} + m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: b98a6db0b653f764eac834f85857a9dd, type: 3} m_Name: m_EditorClassIdentifier: ParadoxNotion::NodeCanvas.Framework.Blackboard - _parentBlackboard: {fileID: 0} - _serializedBlackboard: '{"_variables":{}}' - _objectReferences: [] - _serializedVariables: [] ---- !u!114 &1668865132 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1668865123} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4a7dbb6bbdf4ffb46ab7dd87ba8191e7, type: 3} - m_Name: - m_EditorClassIdentifier: NodeCanvas::NodeCanvas.StateMachines.FSMOwner - _serializedExposedParameters: [] - _boundGraphSerialization: - _boundGraphObjectReferences: [] - _boundGraphSource: - _version: 0 - _category: - _comments: - _translation: {x: 0, y: 0} - _zoomFactor: 1 - _firstActivation: 0 - _enableAction: 0 - _disableAction: 0 - _lockBoundGraphPrefabOverrides: 1 - _preInitializeSubGraphs: 0 - _updateMode: 0 - _graph: {fileID: 11400000, guid: db5b23d2ee7fffd49a42d5a120c50e94, type: 2} - _blackboard: {fileID: 1668865131} ---- !u!114 &1668865133 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1668865123} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: b3b4e13d59527d1429a62dde97c6a001, type: 3} - m_Name: - m_EditorClassIdentifier: Core::Reset.Units.UnitMovementHandler - ShowTopMostFoldoutHeaderGroup: 1 - data: - directionChangingSoftness: - targetValue: 1 - currentValue: 1 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 1 - defaultSmoothing: 1 - defaultEasing: 2 - directionSpinningHardness: - targetValue: 3 - currentValue: 3 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 3 - defaultSmoothing: 1 - defaultEasing: 2 - directionSpinningSpeed: - targetValue: 3 - currentValue: 3 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 3 - defaultSmoothing: 1 - defaultEasing: 2 - airDirectionDecay: - targetValue: 1 - currentValue: 1 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 1 - defaultSmoothing: 1 - defaultEasing: 2 - acceleration: - targetValue: 5 - currentValue: 5 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 5 - defaultSmoothing: 1 - defaultEasing: 2 - deacceleration: - targetValue: 5 - currentValue: 5 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 5 - defaultSmoothing: 1 - defaultEasing: 2 - moveSpeed: - targetValue: 15 - currentValue: 15 - targetSmoothing: 10 - targetEasing: 2 - currentSmoothing: 10 - defaultValue: 15 - defaultSmoothing: 10 - defaultEasing: 2 - gravityPower: - targetValue: 1 - currentValue: 1 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 1 - defaultSmoothing: 1 - defaultEasing: 2 - gravityMax: - targetValue: 8 - currentValue: 8 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 8 - defaultSmoothing: 1 - defaultEasing: 2 - gravityAcceleration: - targetValue: 1 - currentValue: 1 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 1 - defaultSmoothing: 1 - defaultEasing: 2 - gravityScale: - targetValue: 1 - currentValue: 1 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 1 - defaultSmoothing: 1 - defaultEasing: 2 - facingDirection: - targetValue: 4 - currentValue: 4 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 4 - defaultSmoothing: 1 - defaultEasing: 2 - rotationSpeed: - targetValue: 5 - currentValue: 5 - targetSmoothing: 1 - targetEasing: 2 - currentSmoothing: 1 - defaultValue: 5 - defaultSmoothing: 1 - defaultEasing: 2 - specifiedRotation: {x: 0, y: 0, z: 0} --- !u!1 &1698015116 GameObject: m_ObjectHideFlags: 0 @@ -9467,3 +9463,4 @@ SceneRoots: - {fileID: 1291419217} - {fileID: 797489998} - {fileID: 1668865122} + - {fileID: 332821856} diff --git a/Assets/Scripts/Units/Enemy.cs b/Assets/Scripts/Units/Enemy.cs index 94565f5..6420a24 100644 --- a/Assets/Scripts/Units/Enemy.cs +++ b/Assets/Scripts/Units/Enemy.cs @@ -5,7 +5,10 @@ using Unity.Netcode; using UnityEngine; namespace Reset.Units{ - public class Enemy : Unit, ILockOnTarget, IKillable { + public class Enemy : Unit, ILockOnTarget, IKillable{ + // Spawn Info + public EnemySpawn relatedSpawner; + // Lock-On public float lockonTargetRadius{ get; set; } = 10f; [ShowInInspector] diff --git a/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs b/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs index 8025683..9e10e0e 100644 --- a/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs +++ b/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs @@ -1,26 +1,65 @@ -using Pathfinding; +using System.Collections; +using System.Collections.Generic; +using System.Numerics; +using Pathfinding; +using Pathfinding.Drawing; using UnityEngine; +using Vector2 = UnityEngine.Vector2; +using Vector3 = UnityEngine.Vector3; namespace Reset.Units{ - public class EnemyPathfinding : MonoBehaviour, IUnitDirectionProvider{ + [RequireComponent(typeof(Seeker))] + public class EnemyPathfinding : UnitComponent, IUnitDirectionProvider{ public Vector2 Direction{ get; set; } - - public Transform targetPosition; - + private Seeker seeker; - + public float nextWaypointDistance = 3; private int currentWaypoint; public Path path; public bool reachedEndOfPath; + private Coroutine wanderPathCoroutine; + public void Start(){ seeker = GetComponent(); - // If you are writing a 2D game you should remove this line - // and use the alternative way to move sugggested further below. + + Enemy thisEnemy = (Unit as Enemy); + + if (thisEnemy.relatedSpawner){ + seeker.graphMask = GraphMask.FromGraph(thisEnemy.relatedSpawner.relatedGraph); + } else { + Debug.LogWarning("Creating a graph for a singular enemy is not yet implemented. Graph mask not set on this unit.", transform); + } + + StartCoroutine(WaitForWanderPath()); + } - seeker.StartPath(transform.position, targetPosition.position, OnPathComplete); + IEnumerator WaitForWanderPath(){ + yield return new WaitForSeconds(Random.Range(1f, 7f)); + StartWanderPath(); + + wanderPathCoroutine = null; + } + + void StartWanderPath(){ + Enemy thisEnemy = (Unit as Enemy); + Vector3 pathTargetPos = transform.position; + + if (thisEnemy.relatedSpawner) { + pathTargetPos = thisEnemy.relatedSpawner.transform.position; + } + + Vector3 randomizedDestination = new Vector3( + Random.Range(-thisEnemy.relatedSpawner.radius, thisEnemy.relatedSpawner.radius), + 0f, + Random.Range(-thisEnemy.relatedSpawner.radius, thisEnemy.relatedSpawner.radius) + ); + + pathTargetPos += randomizedDestination; + + seeker.StartPath(transform.position, pathTargetPos, OnPathComplete); } public void OnPathComplete(Path p){ @@ -40,6 +79,7 @@ namespace Reset.Units{ reachedEndOfPath = false; // The distance to the next waypoint in the path float distanceToWaypoint; + while (true) { // If you want maximum performance you can check the squared distance instead to get rid of a // square root calculation. But that is outside the scope of this tutorial. @@ -52,22 +92,29 @@ namespace Reset.Units{ // Set a status variable to indicate that the agent has reached the end of the path. // You can use this to trigger some special code if your game requires that. reachedEndOfPath = true; + + if (wanderPathCoroutine == null) { + wanderPathCoroutine = StartCoroutine(WaitForWanderPath()); + } + break; } } else { break; } } + + // Pass the direction to the direction handler interface + if (currentWaypoint + 1 == path.vectorPath.Count) { + Direction = (path.vectorPath[currentWaypoint] - transform.position).ToVector2(); + Direction = Vector3.ClampMagnitude(Direction, 1f); + } else { + Direction = (path.vectorPath[currentWaypoint] - transform.position).normalized.ToVector2(); + } - // Slow down smoothly upon approaching the end of the path - // This value will smoothly go from 1 to 0 as the agent approaches the last waypoint in the path. - var speedFactor = reachedEndOfPath ? Mathf.Sqrt(distanceToWaypoint / nextWaypointDistance) : 1f; - - // Direction to the next waypoint - // Normalize it so that it has a length of 1 world unit - Vector3 dirToPoint = (path.vectorPath[currentWaypoint] - transform.position).normalized * speedFactor; - - Direction = dirToPoint.ToVector2(); + // Draw an indicator for the path + Draw.ingame.SolidCircle(path.vectorPath[currentWaypoint] + Vector3.up * .02f, Vector3.up, .3f); + Draw.ingame.Arrow(transform.position, transform.position + Direction.ToVector3(), Vector3.up, .3f); } } diff --git a/Assets/Scripts/Units/Enemy/EnemySpawn.cs b/Assets/Scripts/Units/Enemy/EnemySpawn.cs index ca1fcae..9368661 100644 --- a/Assets/Scripts/Units/Enemy/EnemySpawn.cs +++ b/Assets/Scripts/Units/Enemy/EnemySpawn.cs @@ -1,47 +1,65 @@ using System.Collections.Generic; using Drawing; +using Pathfinding; using Sirenix.OdinInspector; using UnityEngine; -public class EnemySpawn : MonoBehaviour{ - public float radius = 30f; +namespace Reset.Units{ + public class EnemySpawn : MonoBehaviour{ + public float radius = 30f; - public int minimumEnemies = 1; - public int maximumEnemies = 5; - - public Vector2 enemyCount; + public int minimumEnemies = 1; + public int maximumEnemies = 5; - // TODO: Replace this with an Enemy selector based on difficulty, random chance, etc? - public GameObject enemy; + public Vector2 enemyCount; - public List enemies; - - void Start(){ - SpawnEnemies(); - } + // TODO: Replace this with an Enemy selector based on difficulty, random chance, etc? + public GameObject enemy; - void SpawnEnemies(){ - int count = Random.Range(minimumEnemies, maximumEnemies + 1); + public List enemies; - for (int i = 0; i < count; i++) { - Vector3 newPosition = transform.position; + public GridGraph relatedGraph; - float randomX = Random.Range(-(radius / 2f), radius / 2f); - float randomZ = Random.Range(-(radius / 2f), radius / 2f); + void Start(){ + CreateAstarGraph(); + SpawnEnemies(); + } - newPosition += new Vector3(randomX, transform.position.y, randomZ); + void CreateAstarGraph(){ + relatedGraph = AstarPath.active.data.AddGraph(typeof(GridGraph)) as GridGraph; - float randomRot = Random.Range(0f, 360f); + relatedGraph.SetDimensions(Mathf.FloorToInt(radius) * 2, Mathf.FloorToInt(radius) * 2, 1f); + relatedGraph.collision.diameter = 3f; - GameObject newEnemy = Instantiate(enemy, newPosition, Quaternion.AngleAxis(randomRot, Vector3.up)); - - enemies.Add(newEnemy); + AstarPath.active.Scan(relatedGraph); + + GetComponent().graph = relatedGraph; + } + + void SpawnEnemies(){ + int count = Random.Range(minimumEnemies, maximumEnemies + 1); + + for (int i = 0; i < count; i++) { + Vector3 newPosition = transform.position; + + float randomX = Random.Range(-(radius / 2f), radius / 2f); + float randomZ = Random.Range(-(radius / 2f), radius / 2f); + + newPosition += new Vector3(randomX, transform.position.y, randomZ); + + float randomRot = Random.Range(0f, 360f); + + GameObject newEnemy = Instantiate(enemy, newPosition, Quaternion.AngleAxis(randomRot, Vector3.up)); + newEnemy.GetComponent().relatedSpawner = this; + + enemies.Add(newEnemy); + } + } + + // Update is called once per frame + void Update(){ + Draw.WireCylinder(transform.position, transform.position + Vector3.up * 7f, radius); } } - // Update is called once per frame - void Update() - { - Draw.WireCylinder(transform.position, transform.position + Vector3.up * 7f, radius); - } -} +} \ No newline at end of file