feat: Add HurtBoxOwnerGuard to prevent multiple damage registrations from the same HitBox activation
- Implemented HurtBoxOwnerGuard to ensure that multiple HurtBoxes on the same character do not register damage multiple times during a single HitBox activation. - Added custom editor for HitBox to facilitate the creation of shape colliders with HitBoxColliderProxy. - Introduced PhysicsPerceptionSystem for enemy perception, supporting multiple detection modes including RangeCircle, BatchLOS, FanCast, and BoxCast. - Created EnemyPatrolZone to define patrol and chase areas for enemies, allowing for shared zones among multiple enemies. - Added BD_IsOutsideZone conditional task for Behavior Designer to check if an enemy or player is outside a defined patrol zone.
This commit is contained in:
@@ -2,7 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using BaseGames.Boss;
|
||||
@@ -15,6 +15,8 @@ using BaseGames.Parry;
|
||||
using BaseGames.Player;
|
||||
using BaseGames.Player.States;
|
||||
using BaseGames.Skills;
|
||||
using BaseGames.Editor.Combat;
|
||||
using BaseGames.Editor.Skills;
|
||||
|
||||
namespace BaseGames.Editor
|
||||
{
|
||||
@@ -59,6 +61,7 @@ namespace BaseGames.Editor
|
||||
|
||||
// 小怪类型选择 — 具体敌人类型
|
||||
private int _enemyTypeIndex = 0;
|
||||
private SceneObjectPlacerTool.EnemyBodyColliderType _enemyBodyCollider = SceneObjectPlacerTool.EnemyBodyColliderType.Box;
|
||||
private static readonly (string id, string name)[] EnemyTypes =
|
||||
{
|
||||
("E001", "草蛭"),
|
||||
@@ -195,6 +198,8 @@ namespace BaseGames.Editor
|
||||
|
||||
var jumpGroup = MakeActionGroup();
|
||||
jumpGroup.Add(MakeJumpButton("Data Hub(武器/技能/形态)", DataHubWindow.Open));
|
||||
jumpGroup.Add(MakeJumpButton("武器 HitBox 向导", WeaponHitBoxWizard.Open));
|
||||
jumpGroup.Add(MakeJumpButton("技能 HitBox 向导", SkillHitBoxWizard.Open));
|
||||
jumpGroup.Add(MakeJumpButton("SO 全局校验", SOValidationRunner.ValidateMenu));
|
||||
root.Add(jumpGroup);
|
||||
|
||||
@@ -248,8 +253,9 @@ namespace BaseGames.Editor
|
||||
root.Add(MakeSectionHeader("▶ 专项编辑器"));
|
||||
|
||||
var jumpGroup = MakeActionGroup();
|
||||
jumpGroup.Add(MakeJumpButton("Data Hub(敌人数据)", DataHubWindow.Open));
|
||||
jumpGroup.Add(MakeJumpButton("SO 全局校验", SOValidationRunner.ValidateMenu));
|
||||
jumpGroup.Add(MakeJumpButton("Data Hub(敌人数据)", DataHubWindow.Open));
|
||||
jumpGroup.Add(MakeJumpButton("武器 HitBox 向导", WeaponHitBoxWizard.Open));
|
||||
jumpGroup.Add(MakeJumpButton("SO 全局校验", SOValidationRunner.ValidateMenu));
|
||||
root.Add(jumpGroup);
|
||||
|
||||
return root;
|
||||
@@ -286,11 +292,16 @@ namespace BaseGames.Editor
|
||||
|
||||
container.Add(MakeSeparator());
|
||||
container.Add(MakeSectionHeader("▶ 场景搭建"));
|
||||
container.Add(MakeHelpBox("在当前活动场景中放置完整组件树并自动绑定已有 SO。"));
|
||||
container.Add(MakeHelpBox("在当前活动场景中放置完整组件树(含 Visual 子节点对齐 Collider)并自动绑定已有 SO。"));
|
||||
|
||||
var colliderField = new UnityEngine.UIElements.EnumField("主体碰撞器类型", _enemyBodyCollider);
|
||||
colliderField.RegisterValueChangedCallback(evt => _enemyBodyCollider = (SceneObjectPlacerTool.EnemyBodyColliderType)evt.newValue);
|
||||
container.Add(colliderField);
|
||||
|
||||
var sceneGroup = MakeActionGroup();
|
||||
string sceneLabel = $"放置 {id} {name} 到场景";
|
||||
sceneGroup.Add(MakeSceneButton(sceneLabel, () => PlaceSpecificEnemy(id)));
|
||||
sceneGroup.Add(MakeSceneButton(sceneLabel, () => PlaceSpecificEnemy(id, _enemyBodyCollider)));
|
||||
sceneGroup.Add(MakeSceneButton("迁移选中对象 Visual 节点", MigrateSelectedEnemyVisualNode));
|
||||
container.Add(sceneGroup);
|
||||
}
|
||||
|
||||
@@ -330,15 +341,17 @@ namespace BaseGames.Editor
|
||||
|
||||
var sceneGroup = MakeActionGroup();
|
||||
sceneGroup.Add(MakeSceneButton("放置嘲风到场景并绑定 SO", SceneObjectPlacerTool.PlaceChaoFeng));
|
||||
sceneGroup.Add(MakeSceneButton("迁移选中对象 Visual 节点", MigrateSelectedEnemyVisualNode));
|
||||
root.Add(sceneGroup);
|
||||
|
||||
root.Add(MakeSeparator());
|
||||
root.Add(MakeSectionHeader("▶ 专项编辑器"));
|
||||
|
||||
var jumpGroup = MakeActionGroup();
|
||||
jumpGroup.Add(MakeJumpButton("Boss 技能序列查看器", BossSkillSequenceWindow.OpenWindow));
|
||||
jumpGroup.Add(MakeJumpButton("Data Hub(Boss技能)", DataHubWindow.Open));
|
||||
jumpGroup.Add(MakeJumpButton("SO 全局校验", SOValidationRunner.ValidateMenu));
|
||||
jumpGroup.Add(MakeJumpButton("Boss 技能序列查看器", BossSkillSequenceWindow.OpenWindow));
|
||||
jumpGroup.Add(MakeJumpButton("武器 HitBox 向导", WeaponHitBoxWizard.Open));
|
||||
jumpGroup.Add(MakeJumpButton("Data Hub(Boss技能)", DataHubWindow.Open));
|
||||
jumpGroup.Add(MakeJumpButton("SO 全局校验", SOValidationRunner.ValidateMenu));
|
||||
root.Add(jumpGroup);
|
||||
|
||||
return root;
|
||||
@@ -603,23 +616,45 @@ namespace BaseGames.Editor
|
||||
$"全部 {id} SO 已创建(已存在的跳过)。\n请放置到场景后检查组件绑定。", "确定");
|
||||
}
|
||||
|
||||
private static void PlaceSpecificEnemy(string id)
|
||||
private static void PlaceSpecificEnemy(string id, SceneObjectPlacerTool.EnemyBodyColliderType bodyCollider)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case "E001": SceneObjectPlacerTool.PlaceE001_CaoZhi(); break;
|
||||
case "E002": SceneObjectPlacerTool.PlaceE002_HuangZhi(); break;
|
||||
case "E003": SceneObjectPlacerTool.PlaceE003_YouZhi_Enemy(); break;
|
||||
case "E004": SceneObjectPlacerTool.PlaceE004_ZhiMu_Enemy(); break;
|
||||
case "E005": SceneObjectPlacerTool.PlaceE005_FeiZhi_Enemy(); break;
|
||||
case "E006": SceneObjectPlacerTool.PlaceE006_Huan(); break;
|
||||
case "E001": SceneObjectPlacerTool.PlaceE001_CaoZhi(bodyCollider); break;
|
||||
case "E002": SceneObjectPlacerTool.PlaceE002_HuangZhi(bodyCollider); break;
|
||||
case "E003": SceneObjectPlacerTool.PlaceE003_YouZhi_Enemy(bodyCollider); break;
|
||||
case "E004": SceneObjectPlacerTool.PlaceE004_ZhiMu_Enemy(bodyCollider); break;
|
||||
case "E005": SceneObjectPlacerTool.PlaceE005_FeiZhi_Enemy(bodyCollider); break;
|
||||
case "E006": SceneObjectPlacerTool.PlaceE006_Huan(bodyCollider); break;
|
||||
default:
|
||||
Debug.LogError($"[CharacterWizardWindow] 未注册的敌人 id '{id}',请在 SceneObjectPlacerTool 中实现对应 PlaceE...() 方法并注册。");
|
||||
SceneObjectPlacerTool.PlaceEnemy();
|
||||
SceneObjectPlacerTool.PlaceEnemy(bodyCollider);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void MigrateSelectedEnemyVisualNode()
|
||||
{
|
||||
var targets = Selection.gameObjects;
|
||||
if (targets == null || targets.Length == 0)
|
||||
{
|
||||
EditorUtility.DisplayDialog("迁移 Visual 节点",
|
||||
"请先在 Hierarchy 中选中一个或多个 Enemy 对象。", "确定");
|
||||
return;
|
||||
}
|
||||
int count = 0;
|
||||
foreach (var go in targets)
|
||||
{
|
||||
var movement = go.GetComponent<EnemyMovement>();
|
||||
if (movement != null) { movement.SetupVisualNode(); count++; }
|
||||
}
|
||||
if (count == 0)
|
||||
EditorUtility.DisplayDialog("迁移 Visual 节点",
|
||||
"选中的对象中没有找到 EnemyMovement 组件。", "确定");
|
||||
else
|
||||
Debug.Log($"[CharacterWizardWindow] 已对 {count} 个对象完成 Visual 节点迁移。");
|
||||
}
|
||||
|
||||
// ── SO 资产工厂:嘲风 Boss ─────────────────────────────────────────────
|
||||
|
||||
private static void CreateChaoFengStatsSO()
|
||||
|
||||
Reference in New Issue
Block a user