feat(gameplay): 添加水晶矿资源产出系统和改进AI卡组管理

- 实现水晶矿占领后的能量资源产出功能,包括manaInterval和manaAmount配置
- 添加敌方AI的能量管理系统,支持通过AddMana方法增加能量
- 实现AI卡组轮转机制,包含手牌管理和抽卡队列功能
- 优化单位AI的目标选择和战斗逻辑,修复目标切换问题

- 水晶矿现在可以按设定间隔为所属阵营提供能量资源
-
This commit is contained in:
huadexuan committed 2026-09-21 18:17:05 +08:00
1 parent b185e5768b
commit 06940a849c
21 files changed
+555 -520

No files matched your search

+41 -25
View File
@@ -207,8 +207,17 @@ public class UnitBase : MonoBehaviour
{
navAgent.enabled = false;
}
animator.SetInteger("speed", 0);
// 目标死亡、失活或离开攻击范围时,解除锁定并重新寻敌。
if (!IsTargetValid(target) || !IsWithinAttackReach(target))
{
target = null;
state = State.Alert;
return;
}
attackElapsedTime += Time.deltaTime;
CheckAttackAnimationFinished();
return;
@@ -221,8 +230,10 @@ public class UnitBase : MonoBehaviour
return;
}
//目标决策:周围有敌人打敌人,否则直奔全局攻击标志建筑(默认敌方主城堡)
// 移动/追踪状态持续重新评估目标,确保相遇时能及时攻击敌方单位。
// Attack 状态在上方单独处理,因此不会被这里打断或切换目标。
target = FindTarget();
if (target != null)
{
// 召唤师模式:不主动追击,站定且攻击开关开启时才攻击射程内目标。
@@ -247,21 +258,6 @@ public class UnitBase : MonoBehaviour
}
else
{
//到达使命建筑发现是我方的(增援/占领完成):本单位使命转向敌方主城堡,不影响全局标志
if (target.CompareTag("Building") && IsFriendlyBuilding(target))
{
var myTeam = GetComponent<UnitTeam>();
GameObject castle = AttackTargetController.Instance != null && myTeam != null
? AttackTargetController.Instance.GetEnemyCastleOfTeam(myTeam.teamId)
: null;
if (castle != null)
{
missionTarget = castle; // 使命完成,改打主城堡(单位自身,一次性的)
target = castle;
move(castle.transform.position - transform.position);
return;
}
}
attack(target);
}
@@ -279,6 +275,24 @@ public class UnitBase : MonoBehaviour
public GameObject Target => target;
private bool IsTargetValid(GameObject candidate)
{
if (candidate == null || !candidate.activeInHierarchy)
{
return false;
}
WorldHealthBar healthBar = candidate.GetComponentInParent<WorldHealthBar>();
if (healthBar != null && healthBar.IsDead)
{
return false;
}
UnitTeam myTeam = GetComponent<UnitTeam>();
UnitTeam targetTeam = candidate.GetComponentInParent<UnitTeam>();
return myTeam == null || targetTeam == null || myTeam.IsEnemy(targetTeam.gameObject);
}
public GameObject FindNearestEnemyForSkill()
{
return FindNearestEnemyUnit();
@@ -378,16 +392,19 @@ public class UnitBase : MonoBehaviour
GameObject enemy = FindNearestEnemyUnit();
if (enemy != null) return enemy;
// Phase 2: 出生使命建筑;被销毁时兜底敌方主城堡
if (missionTarget != null && missionTarget.activeInHierarchy)
// Phase 2: 出生使命建筑;只有仍属于敌方的使命建筑才继续攻击。
if (IsTargetValid(missionTarget))
{
return missionTarget;
}
// 使命建筑已被己方占领、失活或销毁时,改攻敌方主城堡。
var myTeam = GetComponent<UnitTeam>();
if (myTeam != null && AttackTargetController.Instance != null)
{
return AttackTargetController.Instance.GetEnemyCastleOfTeam(myTeam.teamId);
GameObject castle = AttackTargetController.Instance.GetEnemyCastleOfTeam(myTeam.teamId);
missionTarget = castle;
return castle;
}
return null;
}
@@ -1064,17 +1081,16 @@ public class UnitBase : MonoBehaviour
//攻击动画结束后恢复当前攻速倍率。
animator.speed = attackSpeedMultiplier;
//攻击动画结束后,目标仍在攻击范围内则立即进行下一次攻击。
target = FindTarget();
if (target != null && IsWithinAttackReach(target))
//攻击结束后只继续攻击当前锁定目标,不在这里重新寻敌。
if (IsTargetValid(target) && IsWithinAttackReach(target))
{
// 攻击结束后可能已切换到新的近距离目标,先更新朝向再开始下一次攻击。
FaceTarget(target);
attack(target);
return;
}
//目标离开攻击范围,回到待机逻辑。
//目标失效或离开攻击范围,解除锁定,下一帧重新寻敌。
target = null;
state = State.Alert;
animator.SetInteger("speed", 0);
}