feat: Update enemy AI and movement systems
- Enhanced Physics2D layer collision report with new interactions between Player and Enemy layers. - Refactored BD_InvestigateLastKnown to streamline animation handling and improve readability. - Simplified BD_MaintainCombatDistance by consolidating movement stop logic. - Updated BD_MoveToPlayer to set AI phase on start. - Improved BD_Patrol logic with better handling of stuck states and path failures. - Enhanced BD_PatrolWaypoints to manage stuck conditions and retry logic more effectively. - Refined BD_ReturnToHome to remove unnecessary animation calls. - Updated BD_WalkRandom to ensure AI phase is set correctly on start. - Improved EnemyAbilityBase to delegate target facing to the movement system. - Enhanced EnemyBase with new movement methods for better control. - Refactored EnemyMovement to introduce a new input system for handling movement and facing. - Added EnemyMoveInput struct to encapsulate movement intentions. - Updated Physics2DSettings to reflect new layer collision matrix. - Introduced RTK CLI instructions for optimized command usage.
This commit is contained in:
@@ -248,7 +248,10 @@ namespace BaseGames.Editor
|
||||
[MenuItem("BaseGames/Scene/Place/Enemy (Basic)", priority = 110)]
|
||||
public static void PlaceEnemy()
|
||||
{
|
||||
var report = new List<string>();
|
||||
var report = new List<string>();
|
||||
int undoGroup = Undo.GetCurrentGroup();
|
||||
Undo.SetCurrentGroupName("Place Basic Enemy");
|
||||
EnemyBase.SuppressValidationWarnings = true;
|
||||
|
||||
GameObject go = new GameObject("BasicEnemy");
|
||||
Undo.RegisterCreatedObjectUndo(go, "Place Enemy");
|
||||
@@ -256,16 +259,23 @@ namespace BaseGames.Editor
|
||||
SetLayer(go, "Enemy", report);
|
||||
|
||||
Rigidbody2D rb = GetOrAddComponent<Rigidbody2D>(go);
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
rb.gravityScale = 2f;
|
||||
rb.constraints = RigidbodyConstraints2D.FreezeRotation;
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
rb.gravityScale = 2f;
|
||||
rb.constraints = RigidbodyConstraints2D.FreezeRotation;
|
||||
rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
|
||||
|
||||
GetOrAddComponent<CapsuleCollider2D>(go);
|
||||
GetOrAddComponent<Animator>(go);
|
||||
SetupSpriteRenderer(go);
|
||||
AnimancerComponent animancer = GetOrAddComponent<AnimancerComponent>(go);
|
||||
SpriteRenderer sr = SetupSpriteRenderer(go);
|
||||
|
||||
EnemyBase enemyBase = GetOrAddComponent<EnemyBase>(go);
|
||||
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
||||
EnemyBase enemyBase = GetOrAddComponent<EnemyBase>(go);
|
||||
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||
GetOrAddComponent<EnemyNavAgent>(go);
|
||||
GetOrAddComponent<NavAgent>(go);
|
||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||
GetOrAddComponent<EnemySensorHub>(go);
|
||||
|
||||
// HurtBox child
|
||||
Transform hurtBoxT = GetOrCreateChild(go.transform, "HurtBox");
|
||||
@@ -283,33 +293,38 @@ namespace BaseGames.Editor
|
||||
HitBox hitBox = GetOrAddComponent<HitBox>(hitBodyT.gameObject);
|
||||
GetOrAddComponent<BodyContactDamage>(hitBodyT.gameObject);
|
||||
|
||||
// References
|
||||
AssignReference(enemyBase, "_stats", enemyStats, report);
|
||||
// Wire EnemyBase
|
||||
AssignReference(enemyBase, "_stats", enemyStats, report);
|
||||
AssignReference(enemyBase, "_movement", movement, report);
|
||||
AssignReference(enemyBase, "_animancer", animancer, report);
|
||||
AssignReference(enemyBase, "_hurtBox", hurtBox, report);
|
||||
|
||||
// DamageSourceSO for body contact (optional — create manually if missing)
|
||||
AssignAsset(enemyBase, "_onEnemyDied", report, false, "EVT_EnemyDied");
|
||||
AssignAsset(enemyBase, "_onPlayerSpawned", report, false, "EVT_PlayerSpawned");
|
||||
AssignAsset(enemyStats, "_onDifficultyChanged", report, false, "EVT_DifficultyChanged");
|
||||
AssignAsset(hurtBox, "_onDamageDealt", report, false, "EVT_DamageDealt");
|
||||
AssignAsset(hurtBox, "_onHitConfirmed", report, false, "EVT_HitConfirmed");
|
||||
|
||||
// Wire EnemyMovement
|
||||
AssignReference(movement, "_animancer", animancer, report);
|
||||
AssignReference(movement, "_spriteRenderer", sr, report);
|
||||
AssignLayerMask(movement, "_groundMask",
|
||||
new[] { "Platform", "OneWayPlatform", "MovingOneWayPlatform", "MidHeightOneWayPlatform" },
|
||||
report);
|
||||
|
||||
// DamageSourceSO for body contact
|
||||
Object dmgSrc = FindFirstAsset("CMB_DS_EnemyBody", "DS_EnemyBody");
|
||||
if (dmgSrc != null)
|
||||
AssignReference(hitBox, "_defaultSource", dmgSrc, report);
|
||||
else
|
||||
report.Add("未找到 DamageSourceSO,HitBox_Body._defaultSource 未绑定。请按规范创建 CMB_DS_EnemyBody.asset。");
|
||||
report.Add("未找到 DamageSourceSO,HitBox_Body._defaultSource 未绑定。请创建 CMB_DS_EnemyBody.asset。");
|
||||
|
||||
// Event channels
|
||||
AssignAsset(enemyBase, "_onEnemyDied", report, false, "EVT_EnemyDied");
|
||||
AssignAsset(enemyBase, "_onPlayerSpawned", report, false, "EVT_PlayerSpawned");
|
||||
AssignAsset(enemyStats, "_onDifficultyChanged", report, false, "EVT_DifficultyChanged");
|
||||
AssignAsset(hurtBox, "_onDamageDealt", report, false, "EVT_DamageDealt");
|
||||
AssignAsset(hurtBox, "_onHitConfirmed", report, false, "EVT_HitConfirmed");
|
||||
|
||||
// EnemyStatsSO (optional)
|
||||
Object enemyStatsSO = FindFirstAsset("BasicEnemyStats", "EnemyStatsSO");
|
||||
if (enemyStatsSO != null)
|
||||
AssignReference(enemyBase, "_statsSO", enemyStatsSO, report);
|
||||
else
|
||||
report.Add("未找到 EnemyStatsSO,EnemyBase._statsSO 未绑定。请在 Data/Enemies/ 创建 ENM_{id}_Stats.asset 后手动指定。");
|
||||
|
||||
report.Add("行为树、导航参数(NavAgent)、动画片段需后续手工挂载。");
|
||||
report.Add("★ 指定 EnemyBase._statsSO、_animConfig 资产(按所创建的敌人类型命名)。");
|
||||
report.Add("★ 挂载行为树 BehaviorTree 组件,指定对应 .asset。");
|
||||
|
||||
Undo.CollapseUndoOperations(undoGroup);
|
||||
Selection.activeGameObject = go;
|
||||
EnemyBase.SuppressValidationWarnings = false;
|
||||
MarkDirtyAndLog("Enemy (Basic)", go, report);
|
||||
}
|
||||
|
||||
@@ -413,6 +428,7 @@ namespace BaseGames.Editor
|
||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||
GetOrAddComponent<EnemyNavAgent>(go);
|
||||
GetOrAddComponent<NavAgent>(go);
|
||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||
EnemySensorHub sensorHub = GetOrAddComponent<EnemySensorHub>(go);
|
||||
|
||||
Transform hurtBoxT = GetOrCreateChild(go.transform, "HurtBox");
|
||||
@@ -455,6 +471,9 @@ namespace BaseGames.Editor
|
||||
AssignAsset(movement, "_animConfig", report, false, "ENM_E001_AnimConfig");
|
||||
AssignReference(movement, "_animancer", animancer, report);
|
||||
AssignReference(movement, "_spriteRenderer", sr1, report);
|
||||
AssignLayerMask(movement, "_groundMask",
|
||||
new[] { "Platform", "OneWayPlatform", "MovingOneWayPlatform", "MidHeightOneWayPlatform" },
|
||||
report);
|
||||
|
||||
AssignAsset(alertAbility, "_config", report, false, "ABL_E001_Alert");
|
||||
AssignAsset(chaseAbility, "_config", report, false, "ABL_E001_Chase");
|
||||
@@ -581,6 +600,7 @@ namespace BaseGames.Editor
|
||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||
GetOrAddComponent<EnemyNavAgent>(go);
|
||||
GetOrAddComponent<NavAgent>(go);
|
||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||
EnemySensorHub sensorHub = GetOrAddComponent<EnemySensorHub>(go);
|
||||
|
||||
Transform hurtBoxT = GetOrCreateChild(go.transform, "HurtBox");
|
||||
@@ -618,8 +638,11 @@ namespace BaseGames.Editor
|
||||
|
||||
AssignAsset(movement, "_config", report, false, "ENM_E003_Stats");
|
||||
AssignAsset(movement, "_animConfig", report, false, "ENM_E003_AnimConfig");
|
||||
AssignReference(movement, "_animancer", animancer, report);
|
||||
AssignReference(movement, "_spriteRenderer", sr3, report);
|
||||
AssignReference(movement, "_animancer", animancer, report);
|
||||
AssignReference(movement, "_spriteRenderer", sr3, report);
|
||||
AssignLayerMask(movement, "_groundMask",
|
||||
new[] { "Platform", "OneWayPlatform", "MovingOneWayPlatform", "MidHeightOneWayPlatform" },
|
||||
report);
|
||||
|
||||
AssignAsset(fallAbility, "_config", report, false, "ABL_E003_Fall");
|
||||
AssignReference(fallAbility, "_contactDamage", bodyContact, report);
|
||||
@@ -668,6 +691,7 @@ namespace BaseGames.Editor
|
||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||
GetOrAddComponent<EnemyNavAgent>(go);
|
||||
GetOrAddComponent<NavAgent>(go);
|
||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||
EnemySensorHub sensorHub = GetOrAddComponent<EnemySensorHub>(go);
|
||||
|
||||
Transform hurtBoxT = GetOrCreateChild(go.transform, "HurtBox");
|
||||
@@ -734,8 +758,11 @@ namespace BaseGames.Editor
|
||||
AssignAsset(movement, "_animConfig", report, false, "ENM_E004_AnimConfig");
|
||||
AssignReference(movement, "_animancer", animancer, report);
|
||||
AssignReference(movement, "_spriteRenderer", sr4, report);
|
||||
AssignLayerMask(movement, "_groundMask",
|
||||
new[] { "Platform", "OneWayPlatform", "MovingOneWayPlatform", "MidHeightOneWayPlatform" },
|
||||
report);
|
||||
|
||||
AssignAsset(biteAbl, "_config", report, false, "ABL_E004_Bite");
|
||||
AssignAsset(biteAbl,"_config", report, false, "ABL_E004_Bite");
|
||||
AssignAsset(slamAbl, "_config", report, false, "ABL_E004_Slam");
|
||||
AssignAsset(acidAbl, "_config", report, false, "ABL_E004_Acid");
|
||||
AssignAsset(chargeAbl, "_config", report, false, "ABL_E004_Charge");
|
||||
@@ -794,6 +821,7 @@ namespace BaseGames.Editor
|
||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||
GetOrAddComponent<EnemyNavAgent>(go);
|
||||
GetOrAddComponent<NavAgent>(go);
|
||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||
EnemySensorHub sensorHub = GetOrAddComponent<EnemySensorHub>(go);
|
||||
|
||||
Transform hurtBoxT = GetOrCreateChild(go.transform, "HurtBox");
|
||||
@@ -837,6 +865,9 @@ namespace BaseGames.Editor
|
||||
AssignAsset(movement, "_animConfig", report, false, "ENM_E005_AnimConfig");
|
||||
AssignReference(movement, "_animancer", animancer, report);
|
||||
AssignReference(movement, "_spriteRenderer", sr5, report);
|
||||
AssignLayerMask(movement, "_groundMask",
|
||||
new[] { "Platform", "OneWayPlatform", "MovingOneWayPlatform", "MidHeightOneWayPlatform" },
|
||||
report);
|
||||
|
||||
AssignAsset(biteAbl, "_config", report, false, "ABL_E005_Bite");
|
||||
AssignAsset(acidAbl, "_config", report, false, "ABL_E005_Acid");
|
||||
@@ -887,6 +918,7 @@ namespace BaseGames.Editor
|
||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||
GetOrAddComponent<EnemyNavAgent>(go);
|
||||
GetOrAddComponent<NavAgent>(go);
|
||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||
EnemySensorHub sensorHub = GetOrAddComponent<EnemySensorHub>(go);
|
||||
|
||||
Transform hurtBoxT = GetOrCreateChild(go.transform, "HurtBox");
|
||||
@@ -936,8 +968,11 @@ namespace BaseGames.Editor
|
||||
AssignAsset(movement, "_animConfig", report, false, "ENM_E006_AnimConfig");
|
||||
AssignReference(movement, "_animancer", animancer, report);
|
||||
AssignReference(movement, "_spriteRenderer", sr6, report);
|
||||
AssignLayerMask(movement, "_groundMask",
|
||||
new[] { "Platform", "OneWayPlatform", "MovingOneWayPlatform", "MidHeightOneWayPlatform" },
|
||||
report);
|
||||
|
||||
AssignAsset(leapAbl, "_config", report, false, "ABL_E006_Leap");
|
||||
AssignAsset(leapAbl,"_config", report, false, "ABL_E006_Leap");
|
||||
AssignAsset(chaseAbl, "_config", report, false, "ABL_E006_Chase");
|
||||
|
||||
AssignReference(leapAbl, "_landingHitBox", landHitBox, report);
|
||||
@@ -992,6 +1027,7 @@ namespace BaseGames.Editor
|
||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||
GetOrAddComponent<EnemyNavAgent>(go);
|
||||
GetOrAddComponent<NavAgent>(go);
|
||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||
BossSkillExecutor skillExec = GetOrAddComponent<BossSkillExecutor>(go);
|
||||
ChaoFengFloatController floatCtrl = GetOrAddComponent<ChaoFengFloatController>(go);
|
||||
ChaoFengKnockdownCounter knockdown = GetOrAddComponent<ChaoFengKnockdownCounter>(go);
|
||||
@@ -1044,6 +1080,9 @@ namespace BaseGames.Editor
|
||||
AssignAsset(movement, "_animConfig", report, false, "ENM_ChaoFeng_AnimConfig");
|
||||
AssignReference(movement, "_animancer", animancer, report);
|
||||
AssignReference(movement, "_spriteRenderer", srBoss, report);
|
||||
AssignLayerMask(movement, "_groundMask",
|
||||
new[] { "Platform", "OneWayPlatform", "MovingOneWayPlatform", "MidHeightOneWayPlatform" },
|
||||
report);
|
||||
|
||||
// Collect BossSkillSOs and assign to executor
|
||||
var skillAssets = new System.Collections.Generic.List<Object>();
|
||||
|
||||
Reference in New Issue
Block a user