mirror of
http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite.git
synced 2025-11-20 12:37:12 +08:00
(client) feat:添加基地界面到游玩界面的过程,添加存档管理,技能树变得可用 (#58)
Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com> Reviewed-on: http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite/pulls/58
This commit is contained in:
109
Client/Assets/Scripts/AI/JobNode_MoveToAttackRange.cs
Normal file
109
Client/Assets/Scripts/AI/JobNode_MoveToAttackRange.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using Data;
|
||||
using Managers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AI
|
||||
{
|
||||
public class JobNode_MoveToAttackRange : LeafNodeBase
|
||||
{
|
||||
private Entity.Entity _targetHostileEntity; // 目标敌对实体
|
||||
private Vector3 _targetMovePosition; // 目标移动位置
|
||||
private bool _isPathSet; // 指示当前是否已设置路径
|
||||
private Vector3 _lastKnownSelfPosition; // 上次已知自身位置
|
||||
|
||||
private int _stuckFrameCount; // 卡住帧计数
|
||||
|
||||
// 卡住检测的常量
|
||||
private const int MAX_STUCK_FRAMES = 10; // 实体在多少帧内没有显著移动,则认为卡住
|
||||
private const float STUCK_POSITION_THRESHOLD_SQ = 0.001f; // 位置变化的平方距离阈值
|
||||
|
||||
// 便利属性,获取实体的攻击范围
|
||||
private float AttackRange => SelfEntity.AttributesNow.attackRange;
|
||||
|
||||
/// <summary>
|
||||
/// 执行移动到攻击范围的逻辑。
|
||||
/// </summary>
|
||||
/// <returns>行为树节点状态。</returns>
|
||||
protected override Status ExecuteLeafLogic()
|
||||
{
|
||||
// 如果路径尚未设置,或目标实体无效(null或死亡),则需要重新寻找目标并设置路径
|
||||
if (!_isPathSet || !_targetHostileEntity || _targetHostileEntity.IsDead)
|
||||
{
|
||||
// 1. 寻找最近的敌对实体
|
||||
var hostileEntityRecord = EntityManager.Instance.FindNearestEntityByRelation(
|
||||
SelfEntity.currentDimensionId,
|
||||
SelfEntity.entityPrefab,
|
||||
Relation.Hostile);
|
||||
|
||||
// 如果没有找到敌对目标,任务失败
|
||||
if (!hostileEntityRecord || !hostileEntityRecord.entity)
|
||||
{
|
||||
return Status.Failure;
|
||||
}
|
||||
|
||||
_targetHostileEntity = hostileEntityRecord.entity;
|
||||
|
||||
// 2. 计算目标移动点(在敌对目标的攻击距离边缘)
|
||||
// 目标点是:从敌对实体指向 SelfEntity 的向量方向上,距离敌对实体 AttackRange 远的点。
|
||||
// 这样做是为了让 SelfEntity 停在敌对实体攻击范围内,而不是直接重叠。
|
||||
Vector3 directionToSelf = (SelfEntity.Position - _targetHostileEntity.Position).normalized;
|
||||
_targetMovePosition = _targetHostileEntity.Position + directionToSelf * AttackRange;
|
||||
|
||||
// 3. 通知 SelfEntity 设置路径目标
|
||||
SelfEntity.SetTarget(_targetMovePosition);
|
||||
_isPathSet = true;
|
||||
_lastKnownSelfPosition = SelfEntity.Position; // 初始化上次已知位置,用于卡住检测
|
||||
_stuckFrameCount = 0; // 重置卡住计数器
|
||||
return Status.Running; // 路径已设置,开始移动
|
||||
}
|
||||
|
||||
// 路径已设置,继续管理移动和卡住检测
|
||||
// 4. 检查是否已到达目标点
|
||||
if (SelfEntity.OnTargetPoint)
|
||||
{
|
||||
return Status.Success; // 成功移动到攻击范围
|
||||
}
|
||||
|
||||
// 5. 卡住检测
|
||||
// 计算当前位置与上次已知位置的平方距离,避免开方运算,提高性能
|
||||
float currentPositionChangeSq = (SelfEntity.Position - _lastKnownSelfPosition).sqrMagnitude;
|
||||
if (currentPositionChangeSq < STUCK_POSITION_THRESHOLD_SQ)
|
||||
{
|
||||
_stuckFrameCount++;
|
||||
if (_stuckFrameCount >= MAX_STUCK_FRAMES)
|
||||
{
|
||||
// 实体长时间未移动,被判定为卡住,需要重新规划路径
|
||||
Debug.LogWarning(
|
||||
$"[{SelfEntity.entityDef.defName}] 行为节点<移动到攻击范围>: 实体卡住了! 重新计算到目标 [{_targetHostileEntity.entityDef.defName}] 的路径。");
|
||||
_isPathSet = false; // 重置此标志,在下一帧会触发重新寻找目标和设置路径
|
||||
return Status.Running; // 尽管卡住,但节点仍然在尝试完成任务
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 实体有移动,重置卡住计数器
|
||||
_stuckFrameCount = 0;
|
||||
}
|
||||
|
||||
// 更新上次已知位置
|
||||
_lastKnownSelfPosition = SelfEntity.Position;
|
||||
|
||||
// 6. 持续移动
|
||||
SelfEntity.TryMove();
|
||||
return Status.Running; // 正在向目标移动
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置此移动节点的所有内部状态。
|
||||
/// </summary>
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset(); // 调用基类的 Reset,重置 CurrentStatus 和 _elapsedFrames
|
||||
_targetHostileEntity = null;
|
||||
_targetMovePosition = Vector3.zero;
|
||||
_isPathSet = false;
|
||||
_lastKnownSelfPosition = Vector3.zero;
|
||||
_stuckFrameCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user