using Data; using Managers; using UnityEngine; namespace AI { public abstract class JobBase { public Entity.Entity entity; protected int timeoutTicks = 300; public bool Running => timeoutTicks > 0; protected abstract void UpdateJob(); public virtual void StartJob(Entity.Entity target) { entity = target; } public bool Update() { if (!Running) return false; UpdateJob(); timeoutTicks--; return true; } public virtual void StopJob() { timeoutTicks = 0; } } public class WanderJob : JobBase { public override void StartJob(Entity.Entity target) { base.StartJob(target); Vector3 move = new(Random.Range(-10, 10), Random.Range(-10, 10)); var targetPosition = entity.transform.position + move; entity.SetTarget(targetPosition); entity.IsChase = false; } protected override void UpdateJob() { entity.TryMove(); } override public void StopJob() { base.StopJob(); entity.IsChase = true; } } public class IdleJob : JobBase { override public void StartJob(Entity.Entity target) { base.StartJob(target); timeoutTicks = 500; } protected override void UpdateJob() { } } public class MoveJob : JobBase { protected override void UpdateJob() { entity.TryMove(); } } public class AttackJob : JobBase { private Entity.Entity attackTarget; // StartJob 方法:用于初始化任务,寻找初始攻击目标 override public void StartJob(Entity.Entity performerEntityContext) // 参数名更明确,通常是发起任务的实体 { base.StartJob(performerEntityContext); // 1. 任务执行者自身有效性检查 if (entity == null) { StopJob(); // 调用StopJob来结束任务 return; } attackTarget = FindNewHostileTarget(); if (attackTarget == null) { StopJob(); // 调用StopJob来结束任务 } } protected override void UpdateJob() { // 1. 任务执行者的基本检查 if (entity == null || entity.IsDead) { StopJob(); return; } if (attackTarget == null || attackTarget.IsDead) { attackTarget = FindNewHostileTarget(); // 尝试寻找新的攻击目标 if (attackTarget == null) { StopJob(); return; } } var weapon = entity.GetCurrentWeapon(); var attackRange = 0f; if (weapon != null) { attackRange = weapon.Attributes.attackRange; } var distanceSq = (entity.Position - attackTarget.Position).sqrMagnitude; var effectiveAttackRangeSq = attackRange * attackRange; // 将攻击范围也平方 entity.SetTarget(attackTarget.Position); if (weapon != null && distanceSq <= effectiveAttackRangeSq) { entity.TryAttack(); } else { entity.TryMove(); } } /// /// 查找执行实体最近的敌对目标。 /// /// 找到的敌对实体,如果没有则返回null。 private Entity.Entity FindNewHostileTarget() { if (!entity) return null; return EntityManage.Instance.FindNearestEntityByRelation( entity.currentDimensionId, // 搜索维度ID entity.entityPrefab, // 执行实体的Prefab ID,用于关系判断 Relation.Hostile)?.entity; // 寻找敌对关系的目标 } } public class AdvancedAttackJob : JobBase { private Entity.Entity attackTarget; // 常量:用于配置远程AI行为的风筝参数 private const float KITING_THRESHOLD_MULTIPLIER = 0.5f; // 当目标距离小于 (攻击范围 * 此乘数) 时,远程单位开始尝试远离 private const float KITING_BUFFER_DISTANCE = 5.0f; // 当远程单位远离时,目标点会是当前位置向反方向偏移此距离 // StartJob 方法:用于初始化任务,寻找初始攻击目标 override public void StartJob(Entity.Entity performerEntityContext) { base.StartJob(performerEntityContext); if (entity == null) { StopJob(); return; } attackTarget = FindNewHostileTarget(); if (attackTarget == null) { StopJob(); } } protected override void UpdateJob() { // 1. 任务执行者的基本检查 if (entity == null || entity.IsDead) { StopJob(); return; } // 2. 攻击目标检查 if (attackTarget == null || attackTarget.IsDead) { attackTarget = FindNewHostileTarget(); // 尝试寻找新的攻击目标 if (attackTarget == null) { StopJob(); return; } } // 获取武器和其属性 var weapon = entity.GetCurrentWeapon(); var attackRange = 0f; var isRangedWeapon = false; // 标识是否为远程武器 if (weapon != null) { if (weapon.Attributes != null) { attackRange = weapon.Attributes.attackRange; } // 使用 WeaponType 来判断武器类型,更明确 isRangedWeapon = weapon.Type == WeaponType.Ranged; } var distanceSq = (entity.Position - attackTarget.Position).sqrMagnitude; var effectiveAttackRangeSq = attackRange * attackRange; // 将攻击范围平方 // ---- 核心AI行为决策 ( AdvancedAttackJob 的智能之处) ---- if (isRangedWeapon) { // 远程单位的风筝(Kiting)逻辑 var kitingDistance = attackRange * KITING_THRESHOLD_MULTIPLIER; var kitingThresholdSq = kitingDistance * kitingDistance; // 过近距离的平方 // 1. 如果目标过于接近 (小于风筝阈值),尝试远离 if (distanceSq < kitingThresholdSq) { // 计算一个远离目标的点作为移动目标 var directionAway = (entity.Position - attackTarget.Position).normalized; var fleePosition = entity.Position + directionAway * KITING_BUFFER_DISTANCE; entity.SetTarget(fleePosition); // 设置远离点为新的移动目标 entity.TryMove(); // 优先执行移动操作以拉开距离 // 在此状态下不进行攻击,专注于 reposition } // 2. 如果目标在最佳攻击范围内 (即在风筝阈值和有效攻击范围之间),则停止移动并攻击 else if (distanceSq <= effectiveAttackRangeSq) { entity.SetTarget(entity.Position); // 设定目标为当前位置,使其停止移动,专注于攻击 entity.TryAttack(); } // 3. 如果目标太远 (超出有效攻击范围),则移动靠近目标 else { entity.SetTarget(attackTarget.Position); // 设置目标位置为移动目标 entity.TryMove(); } } else // 近战单位或没有武器的单位 { entity.SetTarget(attackTarget.Position); if (weapon != null && distanceSq <= effectiveAttackRangeSq) { entity.TryAttack(); } else { entity.TryMove(); } } } /// /// 查找执行实体最近的敌对目标。 /// /// 找到的敌对实体,如果没有则返回null。 private Entity.Entity FindNewHostileTarget() { if (!entity) return null; return EntityManage.Instance.FindNearestEntityByRelation( entity.currentDimensionId, entity.entityPrefab, Relation.Hostile)?.entity; } } }