public interface IAggroTarget {
float GetThreatModifier(AggroType aggroType); // 不同仇恨类型可有不同修正
EntityType GetEntityType(); // 返回实体类型 (Player, TankTower, Nexus)
bool IsValid(); // 是否死亡、隐身或不可作为目标
Vector3 Position { get; }
// 可以添加获取当前血量、是否施法等信息的方法
}
public enum EntityType { Player, TankTower, StandardTower, Minion, Nexus, Obstacle }
public enum AggroType { Damage, Healing, Taunt, Environmental, Ability }
public class AggroAgent : MonoBehaviour { // 挂在怪物身上
// 仇恨列表:Key=目标 (IAggroTarget), Value=当前仇恨值
private Dictionary<IAggroTarget, float> threatTable = new Dictionary<IAggroTarget, float>();
public EntityType monsterType; // 配置怪物自身类型,用于特殊行为
// 在怪物受到伤害、感知到治疗、被嘲讽等时调用
public void AddThreat(IAggroTarget source, AggroType type, float rawValue) {
float threat = rawValue;
// 应用来源的 GetThreatModifier
threat *= source.GetThreatModifier(type);
if (!threatTable.ContainsKey(source)) threatTable[source] = 0;
threatTable[source] += threat;
CleanThreatTable(); // 清理无效目标
CheckSwitchTarget(); // 检查是否需要切换目标
}
// ... (Previous code)
private IAggroTarget FindBestTarget() {
IAggroTarget bestTarget = null;
float highestThreat = -1f;
foreach (var entry in threatTable) {
var target = entry.Key;
float rawThreat = entry.Value;
if (!target.IsValid()) continue;
// 1. 计算 EntityType 优先级修正
float priorityMod = GetPriorityModifier(target.GetEntityType());
// 2. 计算距离权重修正
float distance = Vector3.Distance(transform.position, target.Position);
float distanceFactor = 1f + (distanceSensitivityK / Mathf.Max(distance, 0.1f)); // 防止除以0
// 3. 合成最终仇恨
float finalThreat = rawThreat * priorityMod * distanceFactor;
if (finalThreat > highestThreat) {
highestThreat = finalThreat;
bestTarget = target;
}
}
return bestTarget;
}
private void CheckSwitchTarget() {
IAggroTarget potentialTarget = FindBestTarget();
if (potentialTarget == null || potentialTarget == currentTarget) return;
float currentFinalThreat = CalculateFinalThreat(currentTarget);
float newFinalThreat = CalculateFinalThreat(potentialTarget);
// 阈值判定:防止 Ping-Ponging
float thresholdMultiplier = (IsMeleeRange(potentialTarget)) ? 1.1f : 1.3f;
if (newFinalThreat > currentFinalThreat * thresholdMultiplier) {
SetTarget(potentialTarget);
}
}
private float GetPriorityModifier(EntityType type) {
// 这里可以配置化,或者读取 ScriptableObject 配置
switch (type) {
case EntityType.TankTower: return 5.0f;
case EntityType.Player: return 2.0f;
case EntityType.Nexus: return 10.0f; // 特殊处理
default: return 1.0f;
}
}
}