diff --git a/Client/Assets/Prefab/CharacterPrefab Variant.prefab b/Client/Assets/Prefab/CharacterPrefab Variant.prefab new file mode 100644 index 0000000..9b0023c --- /dev/null +++ b/Client/Assets/Prefab/CharacterPrefab Variant.prefab @@ -0,0 +1,111 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &92380775595425480 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalPosition.x + value: -0.80437 + objectReference: {fileID: 0} + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalPosition.y + value: -3.38364 + objectReference: {fileID: 0} + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 697189026367054479, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 887327274103887133, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: m_Name + value: CharacterPrefab Variant + objectReference: {fileID: 0} + - target: {fileID: 1550000129210799929, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: entity + value: + objectReference: {fileID: 1108911649520063592} + - target: {fileID: 3332598847335032684, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: entity + value: + objectReference: {fileID: 1108911649520063592} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 887327274103887133, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + insertIndex: 2 + addedObject: {fileID: 1108911649520063592} + m_SourcePrefab: {fileID: 100100000, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} +--- !u!1 &943601596972592085 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 887327274103887133, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + m_PrefabInstance: {fileID: 92380775595425480} + m_PrefabAsset: {fileID: 0} +--- !u!114 &1108911649520063592 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 943601596972592085} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 757576bb4354ac54da09868e1be02eec, type: 3} + m_Name: + m_EditorClassIdentifier: + animatorPrefab: {fileID: 2113064398104960506, guid: ea9af70ce0f4c8b4a9de58ac63074156, type: 3} + imagePrefab: {fileID: 1922746734790246249, guid: a6657f26d735fab4690c8185980fda29, type: 3} + healthBarPrefab: {fileID: 8215007830330368681} + direction: {x: 0, y: 0, z: 0} + body: {fileID: 2750404322221410198} + affiliation: + canSelect: 1 + hitBarUIShowTime: 5 +--- !u!1 &2750404322221410198 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 2838206730318674270, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + m_PrefabInstance: {fileID: 92380775595425480} + m_PrefabAsset: {fileID: 0} +--- !u!114 &8215007830330368681 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 8307348883874536545, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + m_PrefabInstance: {fileID: 92380775595425480} + 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/CharacterPrefab Variant.prefab.meta b/Client/Assets/Prefab/CharacterPrefab Variant.prefab.meta new file mode 100644 index 0000000..fed41dc --- /dev/null +++ b/Client/Assets/Prefab/CharacterPrefab Variant.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5218adfb8e855a9459df63de8b2f323c +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Client/Assets/Prefab/EntityPrefab.prefab b/Client/Assets/Prefab/EntityPrefab.prefab index 4e153bc..7ffbbf0 100644 --- a/Client/Assets/Prefab/EntityPrefab.prefab +++ b/Client/Assets/Prefab/EntityPrefab.prefab @@ -97,7 +97,6 @@ GameObject: m_Component: - component: {fileID: 697189026367054479} - component: {fileID: 3332598847335032684} - - component: {fileID: 7300440714681954677} - component: {fileID: 1550000129210799929} - component: {fileID: 1724818962207668775} - component: {fileID: 4717642781780051128} @@ -138,28 +137,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: b20b1846b9ef47db83c2ac8c4c4e82cb, type: 3} m_Name: m_EditorClassIdentifier: - entity: {fileID: 7300440714681954677} + entity: {fileID: 0} outline: {fileID: 1550000129210799929} ---- !u!114 &7300440714681954677 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 887327274103887133} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fbde354e0bcc4409b3378ee9b698ddc0, type: 3} - m_Name: - 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 @@ -176,7 +155,7 @@ MonoBehaviour: outlineRenderer: {fileID: 3992139212329961548} outlineCollider: {fileID: 1724818962207668775} progressBarPrefab: {fileID: 8307348883874536545} - entity: {fileID: 7300440714681954677} + entity: {fileID: 0} --- !u!70 &1724818962207668775 CapsuleCollider2D: m_ObjectHideFlags: 0 diff --git a/Client/Assets/Resources/Default/DefaultEntity.prefab b/Client/Assets/Resources/Default/DefaultEntity.prefab index 6ea4aac..064d79a 100644 --- a/Client/Assets/Resources/Default/DefaultEntity.prefab +++ b/Client/Assets/Resources/Default/DefaultEntity.prefab @@ -130,6 +130,18 @@ PrefabInstance: propertyPath: m_IsActive value: 1 objectReference: {fileID: 0} + - target: {fileID: 1550000129210799929, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: entity + value: + objectReference: {fileID: 8780386748333639840} + - target: {fileID: 1550000129210799929, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: progressBarPrefab + value: + objectReference: {fileID: 0} + - target: {fileID: 3332598847335032684, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + propertyPath: entity + value: + objectReference: {fileID: 8780386748333639840} - target: {fileID: 3992139212329961548, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} propertyPath: m_Enabled value: 0 @@ -139,15 +151,44 @@ PrefabInstance: value: Default objectReference: {fileID: 0} m_RemovedComponents: [] - m_RemovedGameObjects: [] + m_RemovedGameObjects: + - {fileID: 1328271255896522146, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} m_AddedGameObjects: - targetCorrespondingSourceObject: {fileID: 5549544358816209289, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} insertIndex: -1 addedObject: {fileID: 5706548514770437405} - m_AddedComponents: [] + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 887327274103887133, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + insertIndex: 2 + addedObject: {fileID: 8780386748333639840} m_SourcePrefab: {fileID: 100100000, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} --- !u!4 &978302365984264250 stripped Transform: m_CorrespondingSourceObject: {fileID: 5549544358816209289, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} m_PrefabInstance: {fileID: 4652308439801383347} m_PrefabAsset: {fileID: 0} +--- !u!1 &5530484753491532974 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 887327274103887133, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + m_PrefabInstance: {fileID: 4652308439801383347} + m_PrefabAsset: {fileID: 0} +--- !u!114 &8780386748333639840 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5530484753491532974} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fbde354e0bcc4409b3378ee9b698ddc0, type: 3} + m_Name: + m_EditorClassIdentifier: + animatorPrefab: {fileID: 0} + imagePrefab: {fileID: 0} + healthBarPrefab: {fileID: 0} + direction: {x: 0, y: 0, z: 0} + body: {fileID: 0} + affiliation: + canSelect: 1 + hitBarUIShowTime: 5 diff --git a/Client/Assets/Scenes/Start.unity b/Client/Assets/Scenes/Start.unity index 2b1c9bf..0eddb13 100644 --- a/Client/Assets/Scenes/Start.unity +++ b/Client/Assets/Scenes/Start.unity @@ -283,9 +283,11 @@ MonoBehaviour: m_EditorClassIdentifier: isGlobal: 1 entityLevel: {fileID: 1891846098} - entityPrefab: {fileID: 3332598847335032684, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} + entityPrefab: {fileID: 3420474218334607780, guid: 5218adfb8e855a9459df63de8b2f323c, type: 3} buildingLevel: {fileID: 651025902} buildingPrefab: {fileID: 5615006624229444611, guid: d7b9277d8e6ac4541800044bdb0da063, type: 3} + bulletLevel: {fileID: 466785510} + bulletPrefab: {fileID: 8687677644466399534, guid: 29b2450a8636a104586e36333878f4d9, type: 3} defaultEntityPrefab: {fileID: 7975757421877276383, guid: 89661daa5f100c64783f0ad9cd37a7ff, type: 3} --- !u!4 &164739122 Transform: @@ -381,6 +383,37 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &466785510 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 466785511} + m_Layer: 0 + m_Name: BulletLevel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &466785511 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 466785510} + 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: 1423222968} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &603423466 GameObject: m_ObjectHideFlags: 0 @@ -1042,6 +1075,7 @@ Transform: m_Children: - {fileID: 1891846100} - {fileID: 651025903} + - {fileID: 466785511} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1468918169 diff --git a/Client/Assets/Scripts/AI/JobBase.cs b/Client/Assets/Scripts/AI/JobBase.cs index 029257f..fb34311 100644 --- a/Client/Assets/Scripts/AI/JobBase.cs +++ b/Client/Assets/Scripts/AI/JobBase.cs @@ -77,7 +77,7 @@ namespace AI public class TrackPlayerJob : JobBase { private EntityPrefab currentTarget; // 当前追踪的目标玩家 - private List players; // 玩家实体列表 + private LinkedList players; // 玩家实体列表 public override void StartJob(Entity.Entity target) { @@ -87,13 +87,13 @@ namespace AI protected override void UpdateJob() { - if (currentTarget == null || currentTarget.entity.IsDead) + if (!currentTarget || currentTarget.entity.IsDead) { // 如果当前目标无效,则重新查找最近的玩家 UpdateTarget(); } - if (currentTarget != null) + if (currentTarget) { var targetPosition = new Vector3(currentTarget.Position.x, currentTarget.Position.y, 0); entity.SetTarget(targetPosition); @@ -114,7 +114,7 @@ namespace AI currentTarget = GetNearestPlayer(players); } - private EntityPrefab GetNearestPlayer(List players) + private EntityPrefab GetNearestPlayer(LinkedList players) { EntityPrefab nearestPlayer = null; float minDistance = float.MaxValue; @@ -144,7 +144,7 @@ namespace AI protected override void UpdateJob() { - if (player == null || !IsPlayerInRange()) + if (!player || !IsPlayerInRange()) { StopJob(); // 如果玩家不在范围内,停止攻击工作 return; @@ -167,11 +167,11 @@ namespace AI base.StartJob(target); // 查找最近的玩家作为目标 - List players = Managers.EntityManage.Instance.FindEntitiesByFaction("Player"); + LinkedList players = Managers.EntityManage.Instance.FindEntitiesByFaction("Player"); player = GetNearestPlayer(players); } - private EntityPrefab GetNearestPlayer(List players) + private EntityPrefab GetNearestPlayer(LinkedList players) { EntityPrefab nearestPlayer = null; float minDistance = float.MaxValue; @@ -197,7 +197,7 @@ namespace AI private bool IsPlayerValid(EntityPrefab player) { - return player != null && !player.entity.IsDead; + return player && !player.entity.IsDead; } } public class RangedAttackJob : JobBase @@ -206,7 +206,7 @@ namespace AI protected override void UpdateJob() { - if (player == null || !IsPlayerValid(player)) + if (!player || !IsPlayerValid(player)) { StopJob(); // 如果当前目标无效,停止工作 return; @@ -256,11 +256,11 @@ namespace AI base.StartJob(target); // 查找最近的玩家作为目标 - List players = Managers.EntityManage.Instance.FindEntitiesByFaction("Player"); + var players = Managers.EntityManage.Instance.FindEntitiesByFaction("Player"); player = GetNearestPlayer(players); } - private EntityPrefab GetNearestPlayer(List players) + private EntityPrefab GetNearestPlayer(LinkedList players) { EntityPrefab nearestPlayer = null; float minDistance = float.MaxValue; @@ -286,7 +286,7 @@ namespace AI private bool IsPlayerValid(EntityPrefab player) { - return player != null && !player.entity.IsDead; + return player && !player.entity.IsDead; } private const float MaxTrackDistance = 20f; // 最大追踪距离 diff --git a/Client/Assets/Scripts/Data/BuildingDef.cs b/Client/Assets/Scripts/Data/BuildingDef.cs index d9edab4..47a66cc 100644 --- a/Client/Assets/Scripts/Data/BuildingDef.cs +++ b/Client/Assets/Scripts/Data/BuildingDef.cs @@ -1,6 +1,6 @@ namespace Data { - public class BuildingDef : PawnDef + public class BuildingDef : EntityDef { public float slowDown = 0f; } diff --git a/Client/Assets/Scripts/Data/BulletDef.cs b/Client/Assets/Scripts/Data/BulletDef.cs new file mode 100644 index 0000000..523e5c2 --- /dev/null +++ b/Client/Assets/Scripts/Data/BulletDef.cs @@ -0,0 +1,8 @@ +namespace Data +{ + public class BulletDef:EntityDef + { + public string className; + public string value; + } +} \ No newline at end of file diff --git a/Client/Assets/Scripts/Data/BulletDef.cs.meta b/Client/Assets/Scripts/Data/BulletDef.cs.meta new file mode 100644 index 0000000..c333573 --- /dev/null +++ b/Client/Assets/Scripts/Data/BulletDef.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3f32fe058231409aaef631564bc51317 +timeCreated: 1755173999 \ No newline at end of file diff --git a/Client/Assets/Scripts/Data/CharacterDef.cs b/Client/Assets/Scripts/Data/CharacterDef.cs index f918c75..6b8eae0 100644 --- a/Client/Assets/Scripts/Data/CharacterDef.cs +++ b/Client/Assets/Scripts/Data/CharacterDef.cs @@ -7,7 +7,7 @@ using UnityEngine; namespace Data { - public class CharacterDef : PawnDef + public class CharacterDef : EntityDef { } diff --git a/Client/Assets/Scripts/Data/PawnDef.cs b/Client/Assets/Scripts/Data/EntityDef.cs similarity index 89% rename from Client/Assets/Scripts/Data/PawnDef.cs rename to Client/Assets/Scripts/Data/EntityDef.cs index f42cb9a..715bee8 100644 --- a/Client/Assets/Scripts/Data/PawnDef.cs +++ b/Client/Assets/Scripts/Data/EntityDef.cs @@ -5,7 +5,7 @@ using System.Xml.Linq; namespace Data { - public class PawnDef : Define + public class EntityDef : Define { public AttributesDef attributes; public DrawingOrderDef drawingOrder; diff --git a/Client/Assets/Scripts/Data/PawnDef.cs.meta b/Client/Assets/Scripts/Data/EntityDef.cs.meta similarity index 100% rename from Client/Assets/Scripts/Data/PawnDef.cs.meta rename to Client/Assets/Scripts/Data/EntityDef.cs.meta diff --git a/Client/Assets/Scripts/Data/MonsterDef.cs b/Client/Assets/Scripts/Data/MonsterDef.cs index 605b4ea..0dcbcd8 100644 --- a/Client/Assets/Scripts/Data/MonsterDef.cs +++ b/Client/Assets/Scripts/Data/MonsterDef.cs @@ -1,6 +1,6 @@ namespace Data { - public class MonsterDef:PawnDef + public class MonsterDef:EntityDef { } diff --git a/Client/Assets/Scripts/Entity/Bullet.cs b/Client/Assets/Scripts/Entity/Bullet.cs index d88517a..c988c67 100644 --- a/Client/Assets/Scripts/Entity/Bullet.cs +++ b/Client/Assets/Scripts/Entity/Bullet.cs @@ -3,8 +3,14 @@ using UnityEngine; namespace Entity { - public class Bullet:Entity + public class Bullet : Entity { + public override void SetTarget(Vector3 pos) + { + base.SetTarget(pos); + RotateTransformToDirection(transform, direction); + } + protected override void AutoBehave() { TryMove(); @@ -13,6 +19,19 @@ namespace Entity private void OnTriggerEnter2D(Collider2D other) { other.GetComponent()?.OnHit(this); + attributes.health -= 1; + } + // 旋转对象到指定方向 + public static void RotateTransformToDirection(Transform transform, Vector3 targetDirection) + { + // 默认向上方向 + Vector3 upDirection = Vector3.up; + + // 计算旋转角度 + float angle = Mathf.Atan2(targetDirection.x, targetDirection.y) * Mathf.Rad2Deg; + + // 设置旋转 + transform.rotation = Quaternion.Euler(0, 0, angle); } } } \ No newline at end of file diff --git a/Client/Assets/Scripts/Entity/Character.cs b/Client/Assets/Scripts/Entity/Character.cs index fb1b9c5..3f7fbaf 100644 --- a/Client/Assets/Scripts/Entity/Character.cs +++ b/Client/Assets/Scripts/Entity/Character.cs @@ -10,7 +10,7 @@ namespace Entity public class Character : Entity { public CharacterDef characterDef; - + private void Start() { aiTree = new JobGiver_RandomWander(); @@ -22,6 +22,17 @@ namespace Entity if (characterDef == null) return; } - + + public override void TryAttack() + { + if (IsAttacking) + return; + if (!Managers.DefineManager.Instance.defines.TryGetValue(nameof(BulletDef), out var def)) + return; + var buttonDef = def.Values.First(); + Vector3 dir = Utils.MousePosition.GetWorldPosition(); + Managers.EntityManage.Instance.GenerateBulletEntity((BulletDef)buttonDef, Position, + dir - Position); + } } } \ No newline at end of file diff --git a/Client/Assets/Scripts/Entity/Entity.cs b/Client/Assets/Scripts/Entity/Entity.cs index 2e0f55d..8ce491a 100644 --- a/Client/Assets/Scripts/Entity/Entity.cs +++ b/Client/Assets/Scripts/Entity/Entity.cs @@ -134,7 +134,7 @@ namespace Entity // 协程引用 private Coroutine attackCoroutine; - protected PawnDef entityDef; + protected EntityDef entityDef; public float hitBarUIShowTime = 5; @@ -144,14 +144,14 @@ namespace Entity /// /// 初始化实体的基本属性和行为树。 /// - /// 实体的定义数据。 - public virtual void Init(PawnDef pawnDef) + /// 实体的定义数据。 + public virtual void Init(EntityDef entityDef) { - attributes = pawnDef.attributes.Clone(); - aiTree = Utils.BehaviorTree.ConvertToAIBase(pawnDef.behaviorTree); - affiliation = pawnDef.affiliation; - InitBody(pawnDef.drawingOrder); - entityDef = pawnDef; + attributes = entityDef.attributes.Clone(); + aiTree = Utils.BehaviorTree.ConvertToAIBase(entityDef.behaviorTree); + affiliation = entityDef.affiliation; + InitBody(entityDef.drawingOrder); + this.entityDef = entityDef; HideHealthBar(); } @@ -288,9 +288,18 @@ namespace Entity /// 新的朝向。 public virtual void SetOrientation(Orientation orientation) { - bodyNodes[currentOrientation]?.SetActive(false); + // 禁用当前朝向的节点 + if (bodyNodes.TryGetValue(currentOrientation, out var currentNode)) + { + currentNode.SetActive(false); + } + // 设置新的朝向 currentOrientation = orientation; - bodyNodes[orientation]?.SetActive(true); + // 激活新朝向的节点 + if (bodyNodes.TryGetValue(orientation, out var newNode)) + { + newNode.SetActive(true); + } } /// @@ -475,20 +484,13 @@ namespace Entity public void DetectAndAttackEnemies() { - const int attackRange = 3; - var attackCount = 3; - - // 获取攻击范围内的所有碰撞体,使用LayerMask过滤掉非敌人 + var attackCount = attributes.attackTargetCount; + // 获取攻击范围内的所有碰撞体 var hits = Physics2D.OverlapCircleAll( transform.position, - attackRange, + attributes.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) { if (attackCount <= 0) break; diff --git a/Client/Assets/Scripts/Managers/EntityManage.cs b/Client/Assets/Scripts/Managers/EntityManage.cs index 8452ad6..4b593a3 100644 --- a/Client/Assets/Scripts/Managers/EntityManage.cs +++ b/Client/Assets/Scripts/Managers/EntityManage.cs @@ -7,24 +7,29 @@ using UnityEngine; namespace Managers { - public class EntityManage:Utils.MonoSingleton,ITick + public class EntityManage : Utils.MonoSingleton, ITick { - public Dictionary> factionEntities = new(); - + public Dictionary> factionEntities = new(); + public GameObject entityLevel; public EntityPrefab entityPrefab; public GameObject buildingLevel; public EntityPrefab buildingPrefab; - + public GameObject bulletLevel; + public EntityPrefab bulletPrefab; + public EntityPrefab defaultEntityPrefab; - public List FindEntitiesByFaction(string factionKey) + + public LinkedList FindEntitiesByFaction(string factionKey) { if (factionEntities.TryGetValue(factionKey, out var entities)) { return entities; // 如果找到,返回对应的实体列表 } - return new List(); // 如果未找到,返回一个空列表 + + return new(); // 如果未找到,返回一个空列表 } + public void Tick() { foreach (var faction in factionEntities) @@ -43,6 +48,7 @@ namespace Managers itike.Tick(); } } + // 删除所有标记为死亡的实体 foreach (var entityToRemove in entitiesToRemove) { @@ -53,160 +59,186 @@ namespace Managers } /// - /// 根据给定的PawnDef生成一个实体对象。 + /// 根据给定的Def生成实体对象(内部通用方法)。 /// - /// 定义实体属性的PawnDef对象。 - /// 实体生成的位置。 - /// - /// 1. 如果entityPrefab或pawnDef为null,则不会生成实体。 - /// 2. 实体将被创建在entityLevel.transform下。 - /// 3. 使用EntityPrefab组件初始化实体。 - /// - public void GenerateEntity(Data.PawnDef pawnDef, Vector3 pos) + /// 要实例化的预制体 + /// 生成的父级Transform + /// 生成位置 + /// 实体定义对象 + /// 额外的初始化操作(如子弹方向设置) + /// 成功时返回EntityPrefab组件,失败时返回null + private EntityPrefab GenerateEntityInternal( + GameObject prefab, + Transform parent, + Vector3 pos, + Data.EntityDef def, // 所有Def类型需继承自BaseDef + Action extraInit = null) { - // 检查 entityPrefab 是否为空 - if (!entityPrefab) - { - Debug.LogError("Error: entityPrefab is null. Please assign a valid prefab."); - GenerateDefaultEntity(pos); - return; - } - - // 检查 pawnDef 是否为空 - if (pawnDef == null) - { - Debug.LogError("Error: PawnDef is null. Cannot generate entity without a valid PawnDef."); - GenerateDefaultEntity(pos); - return; - } - - GameObject instantiatedEntity = null; // 用于跟踪已实例化的对象 - + GameObject instantiatedEntity = null; try { - // 实例化实体对象 - instantiatedEntity = Instantiate(entityPrefab.gameObject, pos, Quaternion.identity, entityLevel.transform); + // 实例化实体 + instantiatedEntity = Instantiate(prefab, pos, Quaternion.identity, parent); - // 获取 EntityPrefab 组件 + // 获取并验证EntityPrefab组件 var entityComponent = instantiatedEntity.GetComponent(); - - // 检查 EntityPrefab 组件是否存在 if (!entityComponent) { - throw new InvalidOperationException($"Error: EntityPrefab component not found on the instantiated object: {instantiatedEntity.name}"); + throw new InvalidOperationException( + $"EntityPrefab component missing on: {instantiatedEntity.name}"); } - // 初始化实体组件 - entityComponent.Init(pawnDef); - - // 确保派系键存在,并初始化对应的列表 - var factionKey = pawnDef.attributes.label ?? "default"; // 使用 null 合并运算符简化代码 + // 初始化核心数据 + entityComponent.Init(def); + + // 执行类型特有的额外初始化 + extraInit?.Invoke(entityComponent); + + // 管理派系列表 + var factionKey = def.attributes.label ?? "default"; if (!factionEntities.ContainsKey(factionKey)) { - factionEntities[factionKey] = new List(); + factionEntities[factionKey] = new LinkedList(); } - factionEntities[factionKey].Add(entityComponent); + + factionEntities[factionKey].AddLast(entityComponent); + + return entityComponent; } catch (System.Exception ex) { - // 如果有已实例化的对象,则销毁它 - if (instantiatedEntity) - { - Destroy(instantiatedEntity); // 删除已创建的对象 - } + // 清理失败实例 + if (instantiatedEntity) Destroy(instantiatedEntity); - // 捕获并记录任何异常 - Debug.LogError($"An error occurred while generating the entity: {ex.Message}\nStack Trace: {ex.StackTrace}"); - - // 调用默认生成方法 - GenerateDefaultEntity(pos); + Debug.LogError($"Entity generation failed: {ex.Message}\n{ex.StackTrace}"); + return null; } } + /// + /// 根据PawnDef生成普通实体 + /// + public void GenerateEntity(Data.EntityDef entityDef, Vector3 pos) + { + // 验证关键参数 + if (!entityPrefab) + { + Debug.LogError("entityPrefab is null! Assign a valid prefab."); + GenerateDefaultEntity(pos); + return; + } + + if (entityDef == null) + { + Debug.LogError("EntityDef is null! Cannot generate entity."); + GenerateDefaultEntity(pos); + return; + } + + // 调用通用生成逻辑 + var result = GenerateEntityInternal( + entityPrefab.gameObject, + entityLevel.transform, + pos, + entityDef + ); + + if (!result) GenerateDefaultEntity(pos); + } + + /// + /// 生成建筑实体(位置使用Vector3Int) + /// public void GenerateBuildingEntity(Data.BuildingDef buildingDef, Vector3Int pos) { - // 检查 entityPrefab 是否为空 - if (!entityPrefab) + // 修正:检查正确的预制体 (buildingPrefab) + if (!buildingPrefab) { - Debug.LogError("Error: entityPrefab is null. Please assign a valid prefab."); + Debug.LogError("buildingPrefab is null! Assign a valid prefab."); GenerateDefaultEntity(pos); return; } - // 检查 pawnDef 是否为空 if (buildingDef == null) { - Debug.LogError("Error: PawnDef is null. Cannot generate entity without a valid PawnDef."); + Debug.LogError("BuildingDef is null! Cannot generate building."); GenerateDefaultEntity(pos); return; } - GameObject instantiatedEntity = null; // 用于跟踪已实例化的对象 + var worldPos = new Vector3(pos.x, pos.y, pos.z); - try - { - // 实例化实体对象 - instantiatedEntity = Instantiate(buildingPrefab.gameObject, pos, Quaternion.identity, buildingLevel.transform); + var result = GenerateEntityInternal( + buildingPrefab.gameObject, + buildingLevel.transform, + worldPos, + buildingDef + ); - // 获取 EntityPrefab 组件 - var entityComponent = instantiatedEntity.GetComponent(); - - // 检查 EntityPrefab 组件是否存在 - if (!entityComponent) - { - throw new InvalidOperationException($"Error: EntityPrefab component not found on the instantiated object: {instantiatedEntity.name}"); - } - - // 初始化实体组件 - entityComponent.Init(buildingDef); - - // 确保派系键存在,并初始化对应的列表 - var factionKey = buildingDef.attributes.label ?? "default"; // 使用 null 合并运算符简化代码 - if (!factionEntities.ContainsKey(factionKey)) - { - factionEntities[factionKey] = new List(); - } - factionEntities[factionKey].Add(entityComponent); - } - catch (System.Exception ex) - { - // 如果有已实例化的对象,则销毁它 - if (instantiatedEntity) - { - Destroy(instantiatedEntity); // 删除已创建的对象 - } - - // 捕获并记录任何异常 - Debug.LogError($"An error occurred while generating the entity: {ex.Message}\nStack Trace: {ex.StackTrace}"); - - // 调用默认生成方法 - GenerateDefaultEntity(pos); - } + if (!result) GenerateDefaultEntity(pos); } - + + /// + /// 生成子弹实体(含方向设置) + /// + public void GenerateBulletEntity(Data.BulletDef bulletDef, Vector3 pos, Vector3 dir) + { + // 修正:检查正确的预制体 (bulletPrefab) + if (!bulletPrefab) + { + Debug.LogError("bulletPrefab is null! Assign a valid prefab."); + GenerateDefaultEntity(pos); + return; + } + + if (bulletDef == null) + { + Debug.LogError("BulletDef is null! Cannot generate bullet."); + GenerateDefaultEntity(pos); + return; + } + + var result = GenerateEntityInternal( + bulletPrefab.gameObject, + bulletLevel.transform, + pos, + bulletDef, + // 子弹特有的方向设置 + entityComponent => entityComponent.entity.SetTarget(pos + dir) + ); + + if (!result) GenerateDefaultEntity(pos); + } + + /// + /// 生成默认实体(错误回退) + /// public void GenerateDefaultEntity(Vector3 pos) { - var entity = Instantiate(defaultEntityPrefab.gameObject, pos, Quaternion.identity, entityLevel.transform); + var entity = Instantiate(defaultEntityPrefab, pos, Quaternion.identity, entityLevel.transform); var entityComponent = entity.GetComponent(); + const string factionKey = "default"; if (!factionEntities.ContainsKey(factionKey)) { - factionEntities[factionKey] = new List(); + factionEntities[factionKey] = new LinkedList(); } + entityComponent.DefaultInit(); - factionEntities[factionKey].Add(entityComponent); + factionEntities[factionKey].AddLast(entityComponent); } + protected override void OnStart() { factionEntities.Clear(); - + } private void Start() { var pre = Resources.Load("Default/DefaultEntity"); defaultEntityPrefab = pre.GetComponent(); - + } } } \ No newline at end of file diff --git a/Client/Assets/Scripts/Managers/PackagesImageManager.cs b/Client/Assets/Scripts/Managers/PackagesImageManager.cs index 6595b2c..6509325 100644 --- a/Client/Assets/Scripts/Managers/PackagesImageManager.cs +++ b/Client/Assets/Scripts/Managers/PackagesImageManager.cs @@ -377,7 +377,7 @@ namespace Managers // 尝试解析编号 if (int.TryParse(suffix, out var number)) { - sprites.Add((number, Value: value)); + sprites.Add((number, value)); } } } diff --git a/Client/Assets/Scripts/Prefab/EntityPrefab.cs b/Client/Assets/Scripts/Prefab/EntityPrefab.cs index 45f1939..2a73146 100644 --- a/Client/Assets/Scripts/Prefab/EntityPrefab.cs +++ b/Client/Assets/Scripts/Prefab/EntityPrefab.cs @@ -26,9 +26,9 @@ namespace Prefab } } - public void Init(Data.PawnDef pawnDef) + public void Init(Data.EntityDef entityDef) { - entity.Init(pawnDef); + entity.Init(entityDef); outline.Init(); outline.Hide(); diff --git a/Client/Assets/Scripts/UI/DevMenuUI.cs b/Client/Assets/Scripts/UI/DevMenuUI.cs index 72935e0..f22aad3 100644 --- a/Client/Assets/Scripts/UI/DevMenuUI.cs +++ b/Client/Assets/Scripts/UI/DevMenuUI.cs @@ -141,13 +141,13 @@ namespace UI return instantiatedComponent; } - private void GenerateEntityCallback(PawnDef pawnDef) + private void GenerateEntityCallback(EntityDef entityDef) { entityPlacementUI.currentAction = () => { - Managers.EntityManage.Instance.GenerateEntity(pawnDef, Utils.MousePosition.GetWorldPosition()); + Managers.EntityManage.Instance.GenerateEntity(entityDef, Utils.MousePosition.GetWorldPosition()); }; - entityPlacementUI.Prompt = $"当前生成器:\n名称:{pawnDef.label}\n描述:{pawnDef.description}"; + entityPlacementUI.Prompt = $"当前生成器:\n名称:{entityDef.label}\n描述:{entityDef.description}"; entityPlacementUI.snapEnabled = false; Base.UIInputControl.Instance.Show(entityPlacementUI); } diff --git a/Client/Data/Core/Define/Item/Weapon.xml b/Client/Data/Core/Define/Item/Weapon.xml index cc66050..f373d69 100644 --- a/Client/Data/Core/Define/Item/Weapon.xml +++ b/Client/Data/Core/Define/Item/Weapon.xml @@ -21,12 +21,19 @@ yellowBullet - 10 - - Resources\Item\YellowBullet.png - + + 1 + 20 + + + Resources\Item + 20 + + + + - + diff --git a/Client/Data/Core/Resources/Item/YellowBullet.png b/Client/Data/Core/Resources/Item/YellowBullet_down.png similarity index 100% rename from Client/Data/Core/Resources/Item/YellowBullet.png rename to Client/Data/Core/Resources/Item/YellowBullet_down.png