From 35924f3695c1fd674a8fff8009c35694124ee340 Mon Sep 17 00:00:00 2001 From: m0_75251201 Date: Wed, 13 Aug 2025 22:53:57 +0800 Subject: [PATCH] =?UTF-8?q?(client)=20feat:=E5=AE=9E=E7=8E=B0=E8=A1=80?= =?UTF-8?q?=E6=9D=A1=E6=98=BE=E7=A4=BA=EF=BC=8C=E5=AE=9E=E7=8E=B0=E6=94=BB?= =?UTF-8?q?=E5=87=BB=E4=BA=A4=E4=BA=92=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=A2=B0?= =?UTF-8?q?=E6=92=9E=E4=BD=93=EF=BC=9Bfix:=E4=BF=AE=E5=A4=8D=E9=83=A8?= =?UTF-8?q?=E5=88=86=E6=9C=9D=E5=90=91=E8=B4=B4=E5=9B=BE=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9Bchore:?= =?UTF-8?q?=E8=A7=84=E8=8C=83=E5=B7=A5=E4=BD=9C=E7=B1=BB=E5=92=8C=E8=A1=8C?= =?UTF-8?q?=E4=B8=BA=E8=8E=B7=E5=8F=96=E7=B1=BB=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Client/Assets/Prefab/EntityPrefab.prefab | 111 +++++- Client/Assets/Prefab/ProgressBar.prefab | 223 ++++++++++++ Client/Assets/Prefab/ProgressBar.prefab.meta | 7 + .../HighSpeed/Body/Body_Down.png.meta | 6 +- Client/Assets/Scenes/Start.unity | 11 +- Client/Assets/Scripts/AI/AIBase.cs | 36 +- Client/Assets/Scripts/AI/JobGiver.cs | 33 ++ Client/Assets/Scripts/AI/JobGiver.cs.meta | 3 + Client/Assets/Scripts/Base/RightMenu.cs | 11 + Client/Assets/Scripts/Data/AffiliationDef.cs | 13 +- Client/Assets/Scripts/Data/BehaviorTreeDef.cs | 2 +- Client/Assets/Scripts/Data/DrawingOrderDef.cs | 34 +- Client/Assets/Scripts/Data/ItemDef.cs | 14 +- Client/Assets/Scripts/Data/MapDef.cs | 2 + Client/Assets/Scripts/Entity/Character.cs | 2 +- Client/Assets/Scripts/Entity/Entity.cs | 328 ++++++++++++++---- Client/Assets/Scripts/Entity/Inventory.cs | 70 ++++ .../Assets/Scripts/Entity/Inventory.cs.meta | 3 + Client/Assets/Scripts/Entity/Monster.cs | 9 +- Client/Assets/Scripts/Entity/Outline.cs | 20 +- Client/Assets/Scripts/Item.meta | 3 + Client/Assets/Scripts/Item/ItemBase.cs | 12 + Client/Assets/Scripts/Item/ItemBase.cs.meta | 3 + Client/Assets/Scripts/Item/ItemResource.cs | 12 + .../Assets/Scripts/Item/ItemResource.cs.meta | 3 + .../Assets/Scripts/Managers/EntityManage.cs | 2 +- .../Scripts/Managers/ItemResourceManager.cs | 45 +++ .../Managers/ItemResourceManager.cs.meta | 3 + .../Scripts/Managers/PackagesImageManager.cs | 15 +- .../Scripts/Prefab/ProgressBarPrefab.cs | 18 + .../Scripts/Prefab/ProgressBarPrefab.cs.meta | 3 + Client/Assets/Scripts/Utils/BehaviorTree.cs | 75 ++++ .../Assets/Scripts/Utils/BehaviorTree.cs.meta | 3 + .../Core/Define/Building/TowerDefense.xml | 0 Client/Data/Core/Define/Pawn/Character.xml | 12 +- Client/Data/Core/Define/Pawn/Monster.xml | 14 - Client/ProjectSettings/TagManager.asset | 28 +- 37 files changed, 1006 insertions(+), 183 deletions(-) create mode 100644 Client/Assets/Prefab/ProgressBar.prefab create mode 100644 Client/Assets/Prefab/ProgressBar.prefab.meta create mode 100644 Client/Assets/Scripts/AI/JobGiver.cs create mode 100644 Client/Assets/Scripts/AI/JobGiver.cs.meta create mode 100644 Client/Assets/Scripts/Entity/Inventory.cs create mode 100644 Client/Assets/Scripts/Entity/Inventory.cs.meta create mode 100644 Client/Assets/Scripts/Item.meta create mode 100644 Client/Assets/Scripts/Item/ItemBase.cs create mode 100644 Client/Assets/Scripts/Item/ItemBase.cs.meta create mode 100644 Client/Assets/Scripts/Item/ItemResource.cs create mode 100644 Client/Assets/Scripts/Item/ItemResource.cs.meta create mode 100644 Client/Assets/Scripts/Managers/ItemResourceManager.cs create mode 100644 Client/Assets/Scripts/Managers/ItemResourceManager.cs.meta create mode 100644 Client/Assets/Scripts/Prefab/ProgressBarPrefab.cs create mode 100644 Client/Assets/Scripts/Prefab/ProgressBarPrefab.cs.meta create mode 100644 Client/Assets/Scripts/Utils/BehaviorTree.cs create mode 100644 Client/Assets/Scripts/Utils/BehaviorTree.cs.meta delete mode 100644 Client/Data/Core/Define/Building/TowerDefense.xml diff --git a/Client/Assets/Prefab/EntityPrefab.prefab b/Client/Assets/Prefab/EntityPrefab.prefab index 58c99d4..4e153bc 100644 --- a/Client/Assets/Prefab/EntityPrefab.prefab +++ b/Client/Assets/Prefab/EntityPrefab.prefab @@ -100,7 +100,8 @@ GameObject: - component: {fileID: 7300440714681954677} - component: {fileID: 1550000129210799929} - component: {fileID: 1724818962207668775} - m_Layer: 0 + - component: {fileID: 4717642781780051128} + m_Layer: 6 m_Name: EntityPrefab m_TagString: Untagged m_Icon: {fileID: 0} @@ -122,6 +123,7 @@ Transform: m_Children: - {fileID: 5549544358816209289} - {fileID: 1697214530303839877} + - {fileID: 1404278780950315184} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &3332598847335032684 @@ -152,10 +154,12 @@ MonoBehaviour: m_EditorClassIdentifier: animatorPrefab: {fileID: 2113064398104960506, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3} imagePrefab: {fileID: 1922746734790246249, guid: a6657f26d735fab4690c8185980fda29, type: 3} + healthBarPrefab: {fileID: 8307348883874536545} direction: {x: 0, y: 0, z: 0} body: {fileID: 2838206730318674270} affiliation: canSelect: 1 + hitBarUIShowTime: 5 --- !u!114 &1550000129210799929 MonoBehaviour: m_ObjectHideFlags: 0 @@ -171,6 +175,7 @@ MonoBehaviour: body: {fileID: 2838206730318674270} outlineRenderer: {fileID: 3992139212329961548} outlineCollider: {fileID: 1724818962207668775} + progressBarPrefab: {fileID: 8307348883874536545} entity: {fileID: 7300440714681954677} --- !u!70 &1724818962207668775 CapsuleCollider2D: @@ -209,6 +214,33 @@ CapsuleCollider2D: m_Offset: {x: 0, y: 0} m_Size: {x: 1, y: 1} m_Direction: 0 +--- !u!50 &4717642781780051128 +Rigidbody2D: + serializedVersion: 5 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 887327274103887133} + m_BodyType: 0 + m_Simulated: 1 + m_UseFullKinematicContacts: 0 + m_UseAutoMass: 0 + m_Mass: 1 + m_LinearDamping: 0 + m_AngularDamping: 0.05 + m_GravityScale: 0 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_Interpolate: 0 + m_SleepingMode: 1 + m_CollisionDetection: 0 + m_Constraints: 4 --- !u!1 &2838206730318674270 GameObject: m_ObjectHideFlags: 0 @@ -240,3 +272,80 @@ Transform: m_Children: [] m_Father: {fileID: 697189026367054479} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &3478909419655914534 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 697189026367054479} + m_Modifications: + - target: {fileID: 2461610838990723460, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_Name + value: ProgressBar + objectReference: {fileID: 0} + - target: {fileID: 2461610838990723460, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} +--- !u!4 &1404278780950315184 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 2538501538304779414, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + m_PrefabInstance: {fileID: 3478909419655914534} + m_PrefabAsset: {fileID: 0} +--- !u!114 &8307348883874536545 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 4831852659840235591, guid: c9e9ee0f8c58b5b45b2e85c7de8251b0, type: 3} + m_PrefabInstance: {fileID: 3478909419655914534} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 605f185650fe46d89a6e0d60fb8fb11c, type: 3} + m_Name: + m_EditorClassIdentifier: diff --git a/Client/Assets/Prefab/ProgressBar.prefab b/Client/Assets/Prefab/ProgressBar.prefab new file mode 100644 index 0000000..2028603 --- /dev/null +++ b/Client/Assets/Prefab/ProgressBar.prefab @@ -0,0 +1,223 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1422760980158139632 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6758793997642361128} + - component: {fileID: 3249131573413190125} + m_Layer: 0 + m_Name: Square + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6758793997642361128 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1422760980158139632} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.5, y: 0, z: -0.1} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 6523508484757961969} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &3249131573413190125 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1422760980158139632} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} + m_Color: {r: 0.5188679, g: 0.09545213, b: 0.09545213, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 1, y: 1} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!1 &2461610838990723460 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2538501538304779414} + - component: {fileID: 9043291113494845527} + - component: {fileID: 4831852659840235591} + m_Layer: 0 + m_Name: ProgressBar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &2538501538304779414 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2461610838990723460} + 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: 0.1, z: 0.1} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 6523508484757961969} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &9043291113494845527 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2461610838990723460} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 1, y: 1} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!114 &4831852659840235591 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2461610838990723460} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 605f185650fe46d89a6e0d60fb8fb11c, type: 3} + m_Name: + m_EditorClassIdentifier: + _progress: {fileID: 2916926755211552789} +--- !u!1 &2916926755211552789 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6523508484757961969} + m_Layer: 0 + m_Name: GameObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6523508484757961969 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2916926755211552789} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.5, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 6758793997642361128} + m_Father: {fileID: 2538501538304779414} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Client/Assets/Prefab/ProgressBar.prefab.meta b/Client/Assets/Prefab/ProgressBar.prefab.meta new file mode 100644 index 0000000..ec5ff97 --- /dev/null +++ b/Client/Assets/Prefab/ProgressBar.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c9e9ee0f8c58b5b45b2e85c7de8251b0 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Client/Assets/Resources/Character/HighSpeed/Body/Body_Down.png.meta b/Client/Assets/Resources/Character/HighSpeed/Body/Body_Down.png.meta index 216e653..a65b9ff 100644 --- a/Client/Assets/Resources/Character/HighSpeed/Body/Body_Down.png.meta +++ b/Client/Assets/Resources/Character/HighSpeed/Body/Body_Down.png.meta @@ -40,10 +40,10 @@ TextureImporter: wrapU: 0 wrapV: 0 wrapW: 0 - nPOTScale: 1 + nPOTScale: 0 lightmap: 0 compressionQuality: 50 - spriteMode: 0 + spriteMode: 1 spriteExtrude: 1 spriteMeshType: 1 alignment: 0 @@ -100,7 +100,7 @@ TextureImporter: customData: physicsShape: [] bones: [] - spriteID: + spriteID: 5e97eb03825dee720800000000000000 internalID: 0 vertices: [] indices: diff --git a/Client/Assets/Scenes/Start.unity b/Client/Assets/Scenes/Start.unity index 256938f..2b1c9bf 100644 --- a/Client/Assets/Scenes/Start.unity +++ b/Client/Assets/Scenes/Start.unity @@ -135,7 +135,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!212 &111982857 SpriteRenderer: m_ObjectHideFlags: 0 @@ -184,7 +184,7 @@ SpriteRenderer: m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 m_FlipY: 0 - m_DrawMode: 0 + m_DrawMode: 1 m_Size: {x: 1, y: 1} m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 @@ -201,7 +201,7 @@ Transform: serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 2, y: 2, z: 1} + m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} @@ -746,6 +746,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: textureLevel: {fileID: 828003924} + dataOffset: {x: 0, y: 0} --- !u!1 &1236970682 GameObject: m_ObjectHideFlags: 0 @@ -934,8 +935,8 @@ Camera: m_GameObject: {fileID: 1239746123} m_Enabled: 1 serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_ClearFlags: 2 + m_BackGroundColor: {r: 0.26415092, g: 0.26415092, b: 0.26415092, a: 0} m_projectionMatrixMode: 1 m_GateFitMode: 2 m_FOVAxisMode: 0 diff --git a/Client/Assets/Scripts/AI/AIBase.cs b/Client/Assets/Scripts/AI/AIBase.cs index e8b7fe0..a29c041 100644 --- a/Client/Assets/Scripts/AI/AIBase.cs +++ b/Client/Assets/Scripts/AI/AIBase.cs @@ -11,7 +11,7 @@ namespace AI public abstract JobBase GetJob(Entity.Entity target); } - public class Selector : AIBase + public class ThinkNode_Selector : AIBase { public override JobBase GetJob(Entity.Entity target) { @@ -24,13 +24,13 @@ namespace AI return null; } } - public class ConditionalAI : Selector + public class ThinkNode_Conditional : ThinkNode_Selector { // 条件函数,返回 true 表示满足条件 private Func condition; // 构造函数,传入条件函数 - public ConditionalAI(Func conditionFunc) + public ThinkNode_Conditional(Func conditionFunc) { condition = conditionFunc; } @@ -48,7 +48,7 @@ namespace AI return null; } } - public class SequenceAI : AIBase + public class ThinkNode_Sequence : AIBase { public override JobBase GetJob(Entity.Entity target) { @@ -61,33 +61,5 @@ namespace AI return null; // 所有子节点完成时返回 null } } - public class ContinuousMove : AIBase - { - public override JobBase GetJob(Entity.Entity target) - { - return new MoveJob(); - } - } - public class TrackPlayer : AIBase - { - public override JobBase GetJob(Entity.Entity target) - { - return new TrackPlayerJob(); - } - } - public class RandomWander : AIBase - { - public override JobBase GetJob(Entity.Entity target) - { - return new WanderJob(); - } - } - public class Idel : AIBase - { - public override JobBase GetJob(Entity.Entity target) - { - return new IdleJob(); - } - } } \ No newline at end of file diff --git a/Client/Assets/Scripts/AI/JobGiver.cs b/Client/Assets/Scripts/AI/JobGiver.cs new file mode 100644 index 0000000..48ce7bf --- /dev/null +++ b/Client/Assets/Scripts/AI/JobGiver.cs @@ -0,0 +1,33 @@ +namespace AI +{ + public class JobGiver_ContinuousMove : AIBase + { + public override JobBase GetJob(Entity.Entity target) + { + return new MoveJob(); + } + } + + public class JobGiver_Enemies : AIBase + { + public override JobBase GetJob(Entity.Entity target) + { + return new TrackPlayerJob(); + } + } + public class JobGiver_RandomWander : AIBase + { + public override JobBase GetJob(Entity.Entity target) + { + return new WanderJob(); + } + } + public class JobGiver_Idel : AIBase + { + public override JobBase GetJob(Entity.Entity target) + { + return new IdleJob(); + } + } + +} \ No newline at end of file diff --git a/Client/Assets/Scripts/AI/JobGiver.cs.meta b/Client/Assets/Scripts/AI/JobGiver.cs.meta new file mode 100644 index 0000000..db1aded --- /dev/null +++ b/Client/Assets/Scripts/AI/JobGiver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 30648f750dce43e493f5e94cb735988c +timeCreated: 1754974329 \ No newline at end of file diff --git a/Client/Assets/Scripts/Base/RightMenu.cs b/Client/Assets/Scripts/Base/RightMenu.cs index b9acc0c..f972e26 100644 --- a/Client/Assets/Scripts/Base/RightMenu.cs +++ b/Client/Assets/Scripts/Base/RightMenu.cs @@ -9,6 +9,17 @@ namespace Base { public RightMenuPrefab rightMenuPrefab; + public Vector3 Position + { + set + { + rightMenuPrefab.transform.position = value; + } + get + { + return rightMenuPrefab.transform.position; + } + } public void Show() { rightMenuPrefab.Show(); diff --git a/Client/Assets/Scripts/Data/AffiliationDef.cs b/Client/Assets/Scripts/Data/AffiliationDef.cs index 1f61dd0..1668a1d 100644 --- a/Client/Assets/Scripts/Data/AffiliationDef.cs +++ b/Client/Assets/Scripts/Data/AffiliationDef.cs @@ -1,7 +1,18 @@ +using System.Collections.Generic; + namespace Data { + public enum Relation + { + Neutral, + Hostile, + Friendly, + } public class AffiliationDef : Define { - + public Relation defaultRelation = Relation.Neutral; + public List hostileFactions; + public List neutralFactions; + public List friendlyFactions; } } \ No newline at end of file diff --git a/Client/Assets/Scripts/Data/BehaviorTreeDef.cs b/Client/Assets/Scripts/Data/BehaviorTreeDef.cs index edbe63a..2963289 100644 --- a/Client/Assets/Scripts/Data/BehaviorTreeDef.cs +++ b/Client/Assets/Scripts/Data/BehaviorTreeDef.cs @@ -7,7 +7,7 @@ namespace Data public class BehaviorTreeDef : Define { public BehaviorTreeDef[] childTree; - public string className="Selector"; + public string className= "ThinkNode_Selector"; public string value; diff --git a/Client/Assets/Scripts/Data/DrawingOrderDef.cs b/Client/Assets/Scripts/Data/DrawingOrderDef.cs index 5b35821..1ccea9b 100644 --- a/Client/Assets/Scripts/Data/DrawingOrderDef.cs +++ b/Client/Assets/Scripts/Data/DrawingOrderDef.cs @@ -26,37 +26,63 @@ namespace Data public DrawNodeDef drawingOrder_left; public DrawNodeDef drawingOrder_right; public string texturePath; - public int pixelsPerUnit = 16; + public float pixelsPerUnit = 16; - public DrawNodeDef GetDrawingOrder(Orientation orientation) + public DrawNodeDef GetDrawingOrder(Orientation orientation, out Orientation sourceOrientation) { // 定义一个临时变量用于存储结果 DrawNodeDef result = null; + // 初始化 sourceOrientation 为默认值 + sourceOrientation = Orientation.Down; + // 根据传入的 Orientation 获取对应的 DrawingOrderDef switch (orientation) { case Orientation.Down: result = drawingOrder_down; + sourceOrientation = Orientation.Down; break; case Orientation.Up: result = drawingOrder_up; + sourceOrientation = Orientation.Up; break; case Orientation.Left: result = drawingOrder_left; + sourceOrientation = Orientation.Left; break; case Orientation.Right: result = drawingOrder_right; + sourceOrientation = Orientation.Right; break; default: throw new ArgumentException("Invalid orientation value."); } // 如果当前方向的结果为空,则尝试用 drawingOrder_down 填充 - if (result == null) result = drawingOrder_down; + if (result == null) + { + result = drawingOrder_down; + sourceOrientation = Orientation.Down; // 更新 sourceOrientation + } // 如果 drawingOrder_down 仍然为空,则尝试用其他非空方向填充 - if (result == null) result = drawingOrder_up ?? drawingOrder_left ?? drawingOrder_right; + if (result != null) return result; + if (drawingOrder_up != null) + { + result = drawingOrder_up; + sourceOrientation = Orientation.Up; // 更新 sourceOrientation + } + else if (drawingOrder_left != null) + { + result = drawingOrder_left; + sourceOrientation = Orientation.Left; // 更新 sourceOrientation + } + else if (drawingOrder_right != null) + { + result = drawingOrder_right; + sourceOrientation = Orientation.Right; // 更新 sourceOrientation + } return result; } diff --git a/Client/Assets/Scripts/Data/ItemDef.cs b/Client/Assets/Scripts/Data/ItemDef.cs index 1260110..bde94f7 100644 --- a/Client/Assets/Scripts/Data/ItemDef.cs +++ b/Client/Assets/Scripts/Data/ItemDef.cs @@ -1,13 +1,23 @@ namespace Data { + public enum ItemRarity + { + Common, + Uncommon, + Rare, + Epic, + Legendary + } public class ItemDef:Define { public ImageDef texture; - public AttributesDef attributes; + public ItemRarity rarity = ItemRarity.Common; + public int maxStack = 1; // 最大堆叠数量,默认为1 + public bool ssEquippable = false; // 是否可装备 } public class WeaponDef : ItemDef { - + public AttributesDef attributes; } } \ No newline at end of file diff --git a/Client/Assets/Scripts/Data/MapDef.cs b/Client/Assets/Scripts/Data/MapDef.cs index eed84df..56b05a4 100644 --- a/Client/Assets/Scripts/Data/MapDef.cs +++ b/Client/Assets/Scripts/Data/MapDef.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Xml.Linq; +using UnityEngine.Tilemaps; namespace Data { @@ -7,6 +8,7 @@ namespace Data { public ImageDef texture; public string name = ""; + public Tile.ColliderType collider = Tile.ColliderType.None; public override bool Init(XElement xmlDef) { diff --git a/Client/Assets/Scripts/Entity/Character.cs b/Client/Assets/Scripts/Entity/Character.cs index 98b3b0c..fb1b9c5 100644 --- a/Client/Assets/Scripts/Entity/Character.cs +++ b/Client/Assets/Scripts/Entity/Character.cs @@ -13,7 +13,7 @@ namespace Entity private void Start() { - aiTree = new RandomWander(); + aiTree = new JobGiver_RandomWander(); attributes = new AttributesDef(); } diff --git a/Client/Assets/Scripts/Entity/Entity.cs b/Client/Assets/Scripts/Entity/Entity.cs index 371de71..fd27364 100644 --- a/Client/Assets/Scripts/Entity/Entity.cs +++ b/Client/Assets/Scripts/Entity/Entity.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using AI; using Base; @@ -7,23 +8,73 @@ using Prefab; using UnityEngine; using UnityEngine.Serialization; + namespace Entity { + /// + /// 表示游戏中的实体类,继承自 MonoBehaviour 并实现 ITick 接口。 + /// public class Entity : MonoBehaviour, ITick { + /// + /// 动画预制体,用于管理实体的动画逻辑。 + /// public SpriteAnimator animatorPrefab; + + /// + /// 图像预制体,用于管理实体的静态图像显示。 + /// public ImagePrefab imagePrefab; + public ProgressBarPrefab healthBarPrefab; + + + /// + /// 人工智能行为树,定义实体的行为逻辑。 + /// public AIBase aiTree; + + /// + /// 当前实体正在执行的任务。 + /// public JobBase currentJob; + + /// + /// 实体的属性定义,包括生命值、攻击力、防御力等。 + /// public AttributesDef attributes = new(); + + /// + /// 实体当前的移动方向。 + /// public Vector3 direction; + + /// + /// 实体的身体部分,用于挂载动画和图像节点。 + /// public GameObject body; + + /// + /// 实体所属的阵营或派系。 + /// public string affiliation; + /// + /// 表示实体是否可以被选择。 + /// public bool canSelect = true; + /// + /// 表示实体是否处于追逐状态(影响移动速度)。 + /// public bool IsChase { set; get; } = true; + + + + + /// + /// 表示实体是否由玩家控制。 + /// public bool PlayerControlled { set @@ -37,26 +88,76 @@ namespace Entity } get => _isPlayerControlled; } + + /// + /// 获取实体当前位置。 + /// public Vector3 Position => transform.position; + /// + /// 表示实体是否已经死亡(生命值小于等于零)。 + /// public bool IsDead => attributes.health <= 0; private bool _isPlayerControlled = false; private bool _warning = false; + /// + /// 存储不同朝向下的动画节点集合。 + /// public Dictionary> bodyAnimationNode = new(); + + /// + /// 存储不同朝向下的身体节点对象。 + /// private Dictionary bodyNodes = new(); + /// + /// 当前实体的朝向。 + /// private Orientation currentOrientation = Orientation.Down; + + + + /// + /// 攻击动画的持续时间(秒)。 + /// + private const float attackAnimationDuration = 0.1f; + /// + /// 抖动的偏移量。 + /// + private const float shakeOffset = 0.5f; + // 协程引用 + private Coroutine attackCoroutine; + + protected PawnDef entityDef; + + + public float hitBarUIShowTime = 5; + private float hitBarUIShowTimer = 0; + public bool isShowingOfHitBarUI=>hitBarUIShowTimer > 0; + + + /// + /// 初始化实体的基本属性和行为树。 + /// + /// 实体的定义数据。 public virtual void Init(PawnDef pawnDef) { attributes = pawnDef.attributes.Clone(); - aiTree = ConvertToAIBase(pawnDef.behaviorTree); + aiTree = Utils.BehaviorTree.ConvertToAIBase(pawnDef.behaviorTree); affiliation = pawnDef.affiliation; InitBody(pawnDef.drawingOrder); + entityDef = pawnDef; + + HideHealthBar(); } + /// + /// 初始化实体的身体部分,包括不同朝向下的绘图节点。 + /// + /// 绘制顺序定义。 public virtual void InitBody(DrawingOrderDef drawingOrder) { // 定义方向枚举和对应的 GetDrawingOrder 调用 @@ -67,12 +168,12 @@ namespace Entity currentOrientation = orientation; bodyAnimationNode[orientation] = new(); // 获取当前方向的绘图节点 - var drawNode = drawingOrder.GetDrawingOrder(orientation); + var drawNode = drawingOrder.GetDrawingOrder(orientation, out var realOrientation); if (drawNode == null) continue; var directionRoot = new GameObject(orientation.ToString()); directionRoot.transform.SetParent(body.transform, false); - InitBodyPart(drawNode, directionRoot, drawingOrder.texturePath); + InitBodyPart(drawNode, directionRoot, drawingOrder.texturePath,realOrientation); bodyNodes[orientation] = directionRoot; } currentOrientation = Orientation.Down; @@ -84,8 +185,13 @@ namespace Entity SetOrientation(Orientation.Down); } - // 递归初始化单个绘图节点及其子节点 - public virtual void InitBodyPart(DrawNodeDef drawNode, GameObject parent, string folderPath) + /// + /// 递归初始化单个绘图节点及其子节点。 + /// + /// 绘图节点定义。 + /// 父节点对象。 + /// 纹理资源路径。 + public virtual void InitBodyPart(DrawNodeDef drawNode, GameObject parent, string folderPath,Orientation realOrientation) { if (drawNode == null) return; @@ -103,12 +209,11 @@ namespace Entity nodeObject = Instantiate(imagePrefab.gameObject, parent.transform); var texture = Managers.PackagesImageManager.Instance.FindBodyTextures(drawNode.packID, folderPath, - $"{drawNode.nodeName}_{currentOrientation}"); - if (texture.Length > 0) - { - var image = nodeObject.GetComponent(); - image.SetSprite(texture[0]); - } + $"{drawNode.nodeName}_{realOrientation}"); + var image = nodeObject.GetComponent(); + image.SetSprite(texture.Length > 0 + ? texture[0] + : Managers.PackagesImageManager.Instance.defaultSprite); break; case DrawNodeType.Animation: @@ -118,7 +223,7 @@ namespace Entity bodyAnimationNode[currentOrientation].Add(tick); var textures = Managers.PackagesImageManager.Instance.FindBodyTextures(drawNode.packID, folderPath, - $"{drawNode.nodeName}_{currentOrientation}"); + $"{drawNode.nodeName}_{realOrientation}"); var animator = nodeObject.GetComponent(); animator.SetSprites(textures); break; @@ -131,9 +236,13 @@ namespace Entity // 递归初始化子节点 foreach (var child in drawNode.children) { - InitBodyPart(child, nodeObject, folderPath); + InitBodyPart(child, nodeObject, folderPath,realOrientation); } } + + /// + /// 更新实体的逻辑,包括玩家控制和自动行为。 + /// public void Tick() { if (_isPlayerControlled) @@ -151,47 +260,104 @@ namespace Entity tick.Tick(); } } + + if (isShowingOfHitBarUI) + { + hitBarUIShowTimer -= Time.deltaTime; + if (hitBarUIShowTimer <= 0) + { + HideHealthBar(); + } + } } + /// + /// 尝试攻击目标实体。 + /// public virtual void TryAttack() { - + if(attackCoroutine == null) + attackCoroutine = StartCoroutine(AttackFlow()); } + /// + /// 设置实体的朝向。 + /// + /// 新的朝向。 public virtual void SetOrientation(Orientation orientation) { bodyNodes[currentOrientation]?.SetActive(false); currentOrientation = orientation; bodyNodes[orientation]?.SetActive(true); } + /// - /// 往对应朝向移动moveSpeed*deltaTime的距离 + /// 根据方向尝试移动实体。 /// public virtual void TryMove() { transform.position += direction * (attributes.moveSpeed * Time.deltaTime * (IsChase ? 1 : 0.5f)); } + /// + /// 处理实体受到攻击的逻辑。 + /// + /// 攻击来源实体。 public virtual void OnHit(Entity from) { var hit = from.attributes.attack - attributes.defense; if (hit < 0) hit = from.attributes.attack / 100; attributes.health -= hit; - - currentJob.StopJob(); + currentJob?.StopJob(); + ShowHealthBar(); } - public virtual void SetTarget(Vector3 pos) + public void ShowHealthBar() { - direction = (pos - transform.position).normalized; + healthBarPrefab.gameObject.SetActive(true); + healthBarPrefab.Progress = (float)attributes.health / entityDef.attributes.health; + hitBarUIShowTimer=hitBarUIShowTime; } + public void HideHealthBar() + { + healthBarPrefab.gameObject.SetActive(false); + } + + /// + /// 杀死实体,设置生命值为零。 + /// public virtual void Kill() { attributes.health = 0; } + /// + /// 设置实体的目标位置。 + /// + /// 目标位置。 + public virtual void SetTarget(Vector3 pos) + { + direction = (pos - transform.position).normalized; + Orientation ori; + // 判断方向向量最接近哪个朝向 + if (Mathf.Abs(direction.y) > Mathf.Abs(direction.x)) + { + // 垂直方向优先 + ori = direction.y > 0 ? Orientation.Up : Orientation.Down; + } + else + { + // 水平方向优先 + ori = direction.x > 0 ? Orientation.Right : Orientation.Left; + } + SetOrientation(ori); + } + + /// + /// 自动行为逻辑,根据行为树执行任务。 + /// private void AutoBehave() { if (aiTree == null) @@ -213,13 +379,17 @@ namespace Entity currentJob.Update(); } + + /// + /// 更新玩家控制的逻辑,处理输入和移动。 + /// protected virtual void UpdatePlayerControls() { // 检测 Shift 键状态 var isHoldingShift = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift); IsChase = !isHoldingShift; // 按住 Shift 时 IsChase = false,否则 true - // 获取当前键盘输入状态(2D 移动,只使用 X 和 Y 轴) + // 获取当前键盘输入状态(2D 移动,只使用 X 和 Y 轴) var inputDirection = Vector2.zero; // 检测 WASD 或方向键输入 @@ -239,7 +409,10 @@ namespace Entity { inputDirection += Vector2.right; // 向右移动(X 轴正方向) } - + if (Input.GetMouseButtonDown(0)) + { + TryAttack(); + } // 如果有输入方向,则设置目标位置并尝试移动 if (inputDirection == Vector2.zero) return; // 归一化方向向量,确保对角线移动速度一致 @@ -253,61 +426,76 @@ namespace Entity // 调用 TryMove 方法处理实际移动逻辑 TryMove(); + + } - public static AIBase ConvertToAIBase(BehaviorTreeDef behaviorTreeDef) + // 攻击流程协程 + IEnumerator AttackFlow() { - if (behaviorTreeDef == null) - return null; - var aiBase = CreateAIBaseInstance(behaviorTreeDef.className); - if (behaviorTreeDef.childTree != null) - { - foreach (var child in behaviorTreeDef.childTree) - { - if (child != null) - { - aiBase.children.Add(ConvertToAIBase(child)); - } - } - } - return aiBase; + // 播放攻击动画并获取动画持续时间 + var animationDuration = PlayAttackAnimation(); + // 等待动画执行完毕 + yield return new WaitForSeconds(animationDuration); + // 调用检测并攻击敌人的方法 + DetectAndAttackEnemies(); + // 攻击流程结束,清理协程引用 + attackCoroutine = null; } - // 使用反射根据 className 创建具体的 AIBase 子类实例 - private static AIBase CreateAIBaseInstance(string className) + + + + /// + /// 播放攻击动画。 + /// + /// 开始检测攻击范围内敌人的时间。 + public float PlayAttackAnimation() { - if (string.IsNullOrEmpty(className)) - throw new ArgumentException("className 不能为空"); - if (className.Equals("AIBase", StringComparison.OrdinalIgnoreCase)) + // 启动协程来执行攻击动画 + StartCoroutine(ShakeInDirectionCoroutine()); + + // 返回检测敌人的起始时间 + return attackAnimationDuration; + } + + private IEnumerator ShakeInDirectionCoroutine() + { + var originalPosition = transform.position; // 记录原始位置 + transform.position += direction * shakeOffset; + yield return new WaitForSeconds(attackAnimationDuration); + transform.position = originalPosition; + } + + public void DetectAndAttackEnemies() + { + const int attackRange = 3; + var attackCount = 3; + + // 获取攻击范围内的所有碰撞体,使用LayerMask过滤掉非敌人 + var hits = Physics2D.OverlapCircleAll( + transform.position, + attackRange, + LayerMask.GetMask("Entity")); + + // 或者使用标签过滤(如果敌人有特定标签) + // Collider2D[] hits = Physics2D.OverlapCircleAll(transform.position, attackRange); + + Debug.Log($"Found {hits.Length} potential targets in attack range"); + + foreach (var hit in hits) { - return (AIBase)Activator.CreateInstance(typeof(AIBase)); + if (attackCount <= 0) break; + + // 检查是否是自身(额外安全措施) + if (hit.gameObject == this.gameObject) continue; + + // 获取Entity组件 + var entity = hit.GetComponent(); + if (!entity) continue; + + // 执行攻击 + entity.OnHit(this); + attackCount--; } - // 定义可能的命名空间列表 - var possibleNamespaces = new[] { "AI" }; - - foreach (var ns in possibleNamespaces) - { - try - { - // 获取当前程序集 - var assembly = typeof(AIBase).Assembly; - - // 尝试查找类型 - var type = assembly.GetType($"{ns}.{className}"); - - if (type != null && typeof(AIBase).IsAssignableFrom(type)) - { - // 如果找到合适的类型,则创建实例并返回 - return (AIBase)Activator.CreateInstance(type); - } - } - catch - { - // 忽略单个命名空间的错误,继续尝试下一个命名空间 - } - } - - // 如果所有命名空间都未找到对应的类型,抛出异常 - throw new InvalidOperationException($"无法找到类型 {className} 或该类型不是 AIBase 的子类"); } } - } \ No newline at end of file diff --git a/Client/Assets/Scripts/Entity/Inventory.cs b/Client/Assets/Scripts/Entity/Inventory.cs new file mode 100644 index 0000000..5e98860 --- /dev/null +++ b/Client/Assets/Scripts/Entity/Inventory.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using Item; + +namespace Entity +{ + public class Inventory + { + public Entity from; // 物品所属实体 + public List items = new List(); // 背包中的物品列表 + + /// + /// 添加物品到背包 + /// + /// 要添加的物品 + /// 添加的数量 + public void AddItem(ItemResource resource, int count) + { + if (count <= 0) return; // 如果数量小于等于0,直接返回 + + // 检查背包中是否已存在相同物品 + foreach (var item in items) + { + if (item.resource.Equals(resource)) + { + item.count += count; // 增加数量 + return; + } + } + + // 如果没有找到相同物品,则创建新物品并添加到背包 + var newItem = new ItemBase { resource = resource, count = count }; + items.Add(newItem); + } + + /// + /// 从背包中取出物品 + /// + /// 物品名称 + /// 取出的数量 + /// 是否成功取出 + public bool RemoveItem(string itemName, int count) + { + if (count <= 0) return false; // 如果数量小于等于0,直接返回失败 + + foreach (var item in items) + { + if (item.resource.name == itemName) + { + if (item.count >= count) + { + item.count -= count; // 减少数量 + if (item.count == 0) + { + items.Remove(item); // 如果数量为0,则移除该物品 + } + + return true; // 成功取出 + } + else + { + return false; // 数量不足 + } + } + } + return false; // 未找到物品 + } + + + } +} \ No newline at end of file diff --git a/Client/Assets/Scripts/Entity/Inventory.cs.meta b/Client/Assets/Scripts/Entity/Inventory.cs.meta new file mode 100644 index 0000000..1a6b85d --- /dev/null +++ b/Client/Assets/Scripts/Entity/Inventory.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3da96d312e8e4c65b9157548281f7826 +timeCreated: 1755061766 \ No newline at end of file diff --git a/Client/Assets/Scripts/Entity/Monster.cs b/Client/Assets/Scripts/Entity/Monster.cs index e2b2155..dc9a67b 100644 --- a/Client/Assets/Scripts/Entity/Monster.cs +++ b/Client/Assets/Scripts/Entity/Monster.cs @@ -1,12 +1,9 @@ namespace Entity { - public class Monster + public class Monster:Entity { - public Protocol.MonsterPack ToPack() - { - var pack= new Protocol.MonsterPack(); - return pack; - } + + } } \ No newline at end of file diff --git a/Client/Assets/Scripts/Entity/Outline.cs b/Client/Assets/Scripts/Entity/Outline.cs index 721ed1d..b0ae66e 100644 --- a/Client/Assets/Scripts/Entity/Outline.cs +++ b/Client/Assets/Scripts/Entity/Outline.cs @@ -1,5 +1,5 @@ -using System; using System.Collections.Generic; +using Prefab; using UnityEngine; using UnityEngine.Events; @@ -10,6 +10,7 @@ namespace Entity public GameObject body; public SpriteRenderer outlineRenderer; public CapsuleCollider2D outlineCollider; + public ProgressBarPrefab progressBarPrefab; public Entity entity; @@ -23,6 +24,9 @@ namespace Entity outlineRenderer.size = size; outlineCollider.direction = size.x > size.y ? CapsuleDirection2D.Horizontal : CapsuleDirection2D.Vertical; outlineCollider.size = size; + + progressBarPrefab.transform.localPosition += new Vector3(0f,size.y * 2 / 3,0f); + progressBarPrefab.transform.localScale = new Vector3(size.x, size.x / 10, 1); } public void Show() @@ -76,23 +80,23 @@ namespace Entity private void OnMouseEnter() { Show(); - _select = true; } private void OnMouseExit() { Hide(); - _select = false; } private void OnMouseOver() { + if (!entity.canSelect) + return; // 检测是否按下的是鼠标右键 if (Input.GetMouseButtonDown(1)) // 鼠标右键对应的是按钮索引 1 { var rightMenu = Base.RightMenu.Instance; rightMenu.Init(GetMenu()); - rightMenu.transform.position = Input.mousePosition; + rightMenu.Position = Input.mousePosition; rightMenu.Show(); } } @@ -104,6 +108,14 @@ namespace Entity result.Add(("结束操控", EndControl)); else result.Add(("手动操控", StartControl)); + if (CameraControl.CameraControl.Instance.focusedEntity == entity) + { + result.Add(("取消跟随", ()=>CameraControl.CameraControl.Instance.focusedEntity=null)); + } + else + { + result.Add(("视角跟随", ()=>CameraControl.CameraControl.Instance.focusedEntity=entity)); + } result.Add(("杀死", () => entity.Kill())); result.Add(("变成笨蛋", BecomeDefault)); return result; diff --git a/Client/Assets/Scripts/Item.meta b/Client/Assets/Scripts/Item.meta new file mode 100644 index 0000000..08e770a --- /dev/null +++ b/Client/Assets/Scripts/Item.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 89870f1a36ce43558b90c49513f55f10 +timeCreated: 1755061695 \ No newline at end of file diff --git a/Client/Assets/Scripts/Item/ItemBase.cs b/Client/Assets/Scripts/Item/ItemBase.cs new file mode 100644 index 0000000..133bcaf --- /dev/null +++ b/Client/Assets/Scripts/Item/ItemBase.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace Item +{ + public class ItemBase + { + public ItemResource resource; + + public int count=0; + + } +} \ No newline at end of file diff --git a/Client/Assets/Scripts/Item/ItemBase.cs.meta b/Client/Assets/Scripts/Item/ItemBase.cs.meta new file mode 100644 index 0000000..2033845 --- /dev/null +++ b/Client/Assets/Scripts/Item/ItemBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 01a2843d5856483fa5b6967e2e01db62 +timeCreated: 1755061705 \ No newline at end of file diff --git a/Client/Assets/Scripts/Item/ItemResource.cs b/Client/Assets/Scripts/Item/ItemResource.cs new file mode 100644 index 0000000..996fb8e --- /dev/null +++ b/Client/Assets/Scripts/Item/ItemResource.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace Item +{ + public class ItemResource + { + public string name; + public string description; + + public Sprite icon; + } +} \ No newline at end of file diff --git a/Client/Assets/Scripts/Item/ItemResource.cs.meta b/Client/Assets/Scripts/Item/ItemResource.cs.meta new file mode 100644 index 0000000..0782479 --- /dev/null +++ b/Client/Assets/Scripts/Item/ItemResource.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e85c1b3671d1471e85a7ec96eadfabe2 +timeCreated: 1755061828 \ No newline at end of file diff --git a/Client/Assets/Scripts/Managers/EntityManage.cs b/Client/Assets/Scripts/Managers/EntityManage.cs index 460d8c9..8452ad6 100644 --- a/Client/Assets/Scripts/Managers/EntityManage.cs +++ b/Client/Assets/Scripts/Managers/EntityManage.cs @@ -98,7 +98,7 @@ namespace Managers // 初始化实体组件 entityComponent.Init(pawnDef); - + // 确保派系键存在,并初始化对应的列表 var factionKey = pawnDef.attributes.label ?? "default"; // 使用 null 合并运算符简化代码 if (!factionEntities.ContainsKey(factionKey)) diff --git a/Client/Assets/Scripts/Managers/ItemResourceManager.cs b/Client/Assets/Scripts/Managers/ItemResourceManager.cs new file mode 100644 index 0000000..b7b11a2 --- /dev/null +++ b/Client/Assets/Scripts/Managers/ItemResourceManager.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Linq; +using Data; +using Item; + +namespace Managers +{ + public class ItemResourceManager:Utils.Singleton + { + //定义名,物品 + public Dictionary items; + + + public void Init() + { + var itemDefs = Managers.DefineManager.Instance.QueryDefinesByType(); + foreach (var itemDef in itemDefs) + { + var item=new Item.ItemResource(); + item.name = itemDef.label; + item.description = itemDef.description; + + item.icon = Managers.PackagesImageManager.Instance.GetSprite(itemDef.texture); + } + } + + public ItemResource GetItem(string defName) + { + return items.GetValueOrDefault(defName,null); + } + // + /// 按物品名称查找物品 + /// + /// 要查找的物品名称 + /// 找到的物品对象,如果未找到则返回 null + public ItemResource FindItemByName(string itemName) + { + if (string.IsNullOrEmpty(itemName)) + { + return null; + } + return items.Values.FirstOrDefault(item => item.name == itemName); + } + } +} \ No newline at end of file diff --git a/Client/Assets/Scripts/Managers/ItemResourceManager.cs.meta b/Client/Assets/Scripts/Managers/ItemResourceManager.cs.meta new file mode 100644 index 0000000..f7506fa --- /dev/null +++ b/Client/Assets/Scripts/Managers/ItemResourceManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eafd50f3a0594a6e845ecf87b04744ce +timeCreated: 1755062360 \ No newline at end of file diff --git a/Client/Assets/Scripts/Managers/PackagesImageManager.cs b/Client/Assets/Scripts/Managers/PackagesImageManager.cs index 4a25984..6595b2c 100644 --- a/Client/Assets/Scripts/Managers/PackagesImageManager.cs +++ b/Client/Assets/Scripts/Managers/PackagesImageManager.cs @@ -90,16 +90,16 @@ namespace Managers } // 判断是否为 Unity 资源路径 - bool isUnityResource = drawOrder.texturePath.StartsWith("res:", StringComparison.OrdinalIgnoreCase); - string rootPath = packRootSite[drawOrder.packID]; + var isUnityResource = drawOrder.texturePath.StartsWith("res:", StringComparison.OrdinalIgnoreCase); + var rootPath = packRootSite[drawOrder.packID]; if (isUnityResource) { // 移除 "res:" 前缀并适配 Unity 资源路径规则 - string resourceFolder = drawOrder.texturePath.Substring(4).TrimStart('/').Replace('\\', '/'); + var resourceFolder = drawOrder.texturePath.Substring(4).TrimStart('/').Replace('\\', '/'); // 加载文件夹下的所有纹理资源 - Texture2D[] textures = Resources.LoadAll(resourceFolder); + var textures = Resources.LoadAll(resourceFolder); if (textures == null || textures.Length == 0) { Debug.LogWarning($"No textures found in Unity resource folder: {resourceFolder}"); @@ -124,7 +124,6 @@ namespace Managers new Vector2(0.5f, 0.5f), // 中心点 drawOrder.pixelsPerUnit ); - var name = image.name; // 插入纹理 @@ -269,7 +268,11 @@ namespace Managers sprites.Clear(); Init(); } - + + public Sprite GetSprite(ImageDef ima) + { + return GetSprite(ima.packID,ima.name); + } public Sprite GetSprite(string packID, string name) { if (string.IsNullOrEmpty(packID)) diff --git a/Client/Assets/Scripts/Prefab/ProgressBarPrefab.cs b/Client/Assets/Scripts/Prefab/ProgressBarPrefab.cs new file mode 100644 index 0000000..7dff0f1 --- /dev/null +++ b/Client/Assets/Scripts/Prefab/ProgressBarPrefab.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace Prefab +{ + public class ProgressBarPrefab:MonoBehaviour + { + public GameObject _progress; + public float Progress + { + get => _progress.transform.localScale.x; + set + { + var x=Mathf.Clamp01(value); + _progress.transform.localScale = new Vector3(x, _progress.transform.localScale.y, _progress.transform.localScale.z); + } + } + } +} \ No newline at end of file diff --git a/Client/Assets/Scripts/Prefab/ProgressBarPrefab.cs.meta b/Client/Assets/Scripts/Prefab/ProgressBarPrefab.cs.meta new file mode 100644 index 0000000..0e611d7 --- /dev/null +++ b/Client/Assets/Scripts/Prefab/ProgressBarPrefab.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 605f185650fe46d89a6e0d60fb8fb11c +timeCreated: 1755091112 \ No newline at end of file diff --git a/Client/Assets/Scripts/Utils/BehaviorTree.cs b/Client/Assets/Scripts/Utils/BehaviorTree.cs new file mode 100644 index 0000000..16fd222 --- /dev/null +++ b/Client/Assets/Scripts/Utils/BehaviorTree.cs @@ -0,0 +1,75 @@ +using System; +using AI; +using Data; + +namespace Utils +{ + + public static class BehaviorTree + { + /// + /// 将行为树定义转换为 AIBase 类型。 + /// + /// 行为树定义。 + /// 转换后的 AIBase 实例。 + public static AIBase ConvertToAIBase(BehaviorTreeDef behaviorTreeDef) + { + if (behaviorTreeDef == null) + return null; + var aiBase = CreateAIBaseInstance(behaviorTreeDef.className); + if (behaviorTreeDef.childTree != null) + { + foreach (var child in behaviorTreeDef.childTree) + { + if (child != null) + { + aiBase.children.Add(ConvertToAIBase(child)); + } + } + } + return aiBase; + } + + /// + /// 使用反射根据类名创建 AIBase 的具体子类实例。 + /// + /// 类名。 + /// 创建的 AIBase 子类实例。 + private static AIBase CreateAIBaseInstance(string className) + { + if (string.IsNullOrEmpty(className)) + throw new ArgumentException("className 不能为空"); + if (className.Equals("AIBase", StringComparison.OrdinalIgnoreCase)) + { + return (AIBase)Activator.CreateInstance(typeof(AIBase)); + } + // 定义可能的命名空间列表 + var possibleNamespaces = new[] { "AI" }; + + foreach (var ns in possibleNamespaces) + { + try + { + // 获取当前程序集 + var assembly = typeof(AIBase).Assembly; + + // 尝试查找类型 + var type = assembly.GetType($"{ns}.{className}"); + + if (type != null && typeof(AIBase).IsAssignableFrom(type)) + { + // 如果找到合适的类型,则创建实例并返回 + return (AIBase)Activator.CreateInstance(type); + } + } + catch + { + // 忽略单个命名空间的错误,继续尝试下一个命名空间 + } + } + + // 如果所有命名空间都未找到对应的类型,抛出异常 + throw new InvalidOperationException($"无法找到类型 {className} 或该类型不是 AIBase 的子类"); + } + } +} \ No newline at end of file diff --git a/Client/Assets/Scripts/Utils/BehaviorTree.cs.meta b/Client/Assets/Scripts/Utils/BehaviorTree.cs.meta new file mode 100644 index 0000000..16392eb --- /dev/null +++ b/Client/Assets/Scripts/Utils/BehaviorTree.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6b711456a12f4bf6a29b0de14a2d7d8f +timeCreated: 1754982046 \ No newline at end of file diff --git a/Client/Data/Core/Define/Building/TowerDefense.xml b/Client/Data/Core/Define/Building/TowerDefense.xml deleted file mode 100644 index e69de29..0000000 diff --git a/Client/Data/Core/Define/Pawn/Character.xml b/Client/Data/Core/Define/Pawn/Character.xml index 3eb90e5..6685f25 100644 --- a/Client/Data/Core/Define/Pawn/Character.xml +++ b/Client/Data/Core/Define/Pawn/Character.xml @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -51,13 +51,13 @@ player res:Character\HighSpeed - 100 + 200 - + @@ -72,13 +72,13 @@ player res:Character\HighSpeed + 200 - - + diff --git a/Client/Data/Core/Define/Pawn/Monster.xml b/Client/Data/Core/Define/Pawn/Monster.xml index 7067a4f..18b0ce7 100644 --- a/Client/Data/Core/Define/Pawn/Monster.xml +++ b/Client/Data/Core/Define/Pawn/Monster.xml @@ -6,20 +6,6 @@ embrace - - - - - - - - - - - - - - diff --git a/Client/ProjectSettings/TagManager.asset b/Client/ProjectSettings/TagManager.asset index 6413d11..9847431 100644 --- a/Client/ProjectSettings/TagManager.asset +++ b/Client/ProjectSettings/TagManager.asset @@ -2,7 +2,7 @@ %TAG !u! tag:unity3d.com,2011: --- !u!78 &1 TagManager: - serializedVersion: 2 + serializedVersion: 3 tags: [] layers: - Default @@ -11,7 +11,7 @@ TagManager: - - Water - UI - - + - Entity - - - @@ -50,27 +50,3 @@ TagManager: - Light Layer 5 - Light Layer 6 - Light Layer 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -