feat(buildings): 添加金矿建筑功能并优化建筑健康系统

- 为兵营和金矿添加伤害数字显示功能,包括持续时间、上升高度等参数
- 将金矿脚本重构为GoldMine组件,实现定时产出金币机制
- 为所有单位添加NavMeshAgent组件以支持导航寻路
- 为弓箭手、法师等单位添加分离半径和目标扩散参数
- 为建筑添加碰撞体和标签设置
- 修复当前能量字段命名规范(currentEnergy -> _currentEnergy)
- 调整金矿健康值从100提升至500
- 统一伤害数字显示相关属性配置
```
This commit is contained in:
huadexuan committed 2026-09-15 21:13:44 +08:00
1 parent 27df2aa8b1
commit 1cdb7c3910
22 files changed
+804 -55

No files matched your search

+45 -19
View File
@@ -14,7 +14,19 @@ public class WorldHealthBar : MonoBehaviour
[Min(1f)] public float maxEnergy = 100f;
// 当前技能能量,范围会自动限制在 0 到 maxEnergy 之间。
[Min(0f)] public float currentEnergy = 0f;
[Min(0f)]
[SerializeField]
private float _currentEnergy = 0f;
public float currentEnergy
{
get => _currentEnergy;
set
{
_currentEnergy = Mathf.Clamp(value, 0f, maxEnergy);
UpdateEnergyFill();
}
}
public bool IsEnergyFull => !isDead && currentEnergy >= maxEnergy;
@@ -39,16 +51,18 @@ public class WorldHealthBar : MonoBehaviour
[Min(0f)] public float damageNumberRiseHeight = 1.2f;
[Min(0f)] public float damageNumberSpawnHeight = 1.5f;
[Min(0.01f)] public float damageNumberSize = 0.09f;
[Min(0f)] public float damageNumberOutlineWidth = 0.015f;
// 描边宽度设为私有常量,所有角色统一使用
private const float DamageNumberOutlineWidth = 0.025f; // 从 0.015 增加到 0.025,描边更粗
// 血条 UI 的像素尺寸,实际显示大小由 worldWidth 控制。
private const int PixelWidth = 100;
private const int PixelHeight = 14;
// 能量条紧贴血条下方,宽度更窄,高度更小。
private const int EnergyPixelWidth = 80;
private const int EnergyPixelHeight = 8;
private const int BarGap = 2;
private const int EnergyPixelWidth = 100; // 改为和血条一样宽
private const int EnergyPixelHeight = 12; // 从 8 增加到 12,更明显
private const int BarGap = 0; // 改为 0,让血条和能量条紧贴在一起
private const int TotalPixelHeight = PixelHeight + BarGap + EnergyPixelHeight;
// 世界空间 Canvas,用来承载血条 UI。
@@ -81,7 +95,7 @@ public class WorldHealthBar : MonoBehaviour
maxHealth = Mathf.Max(1f, maxHealth);
currentHealth = Mathf.Clamp(currentHealth, 0f, maxHealth);
maxEnergy = Mathf.Max(1f, maxEnergy);
currentEnergy = Mathf.Clamp(currentEnergy, 0f, maxEnergy);
_currentEnergy = Mathf.Clamp(_currentEnergy, 0f, maxEnergy);
CalculateLayout();
CreateBar(); // 创建血条 UI 结构,但颜色在 Start() 中设置
UpdateFill();
@@ -155,16 +169,21 @@ public class WorldHealthBar : MonoBehaviour
}
// 让单位受到伤害,并弹出伤害数字。
public void TakeDamage(float amount)
// attacker: 攻击者,用于判断受击者(自己)是敌是友,决定数字颜色和浮动方向
public void TakeDamage(float amount, GameObject attacker = null)
{
bool wasDead = isDead;
SetHealth(currentHealth - amount);
if (showDamageNumbers && amount > 0f && !wasDead)
{
SpawnDamageNumber(amount, false);
// 判断受击者(自己)是否是友方(Friend tag)
bool isVictimFriend = gameObject.CompareTag("Friend");
SpawnDamageNumber(amount, false, isVictimFriend);
}
}
// 不再需要这个方法,直接用 CompareTag 判断
// 让单位恢复生命值,并弹出绿色治疗数字。
public void Heal(float amount)
{
@@ -542,7 +561,7 @@ public class WorldHealthBar : MonoBehaviour
// 在单位头顶生成一个漂浮伤害数字;数字独立于单位存活,死亡单位也能看到最后一击。
// TextMesh 不支持原生描边,用 4 个偏移的黑色副本 + 1 个白色主字组合出黑边效果。
private void SpawnDamageNumber(float amount, bool isHeal)
private void SpawnDamageNumber(float amount, bool isHeal, bool isVictimFriend = false)
{
if (DamageNumber.ActiveCount >= DamageNumber.MaxActive)
{
@@ -555,19 +574,26 @@ public class WorldHealthBar : MonoBehaviour
rootObject.transform.position = spawnPosition;
string text = Mathf.RoundToInt(amount).ToString();
float outline = damageNumberOutlineWidth;
float outline = DamageNumberOutlineWidth;
// 黑色描边副本先画(sortingOrder 低)。
CreateNumberText(rootObject.transform, text, new Vector3(-outline, 0f, 0f), Color.black, damageNumberSize, 60);
CreateNumberText(rootObject.transform, text, new Vector3(outline, 0f, 0f), Color.black, damageNumberSize, 60);
CreateNumberText(rootObject.transform, text, new Vector3(0f, -outline, 0f), Color.black, damageNumberSize, 60);
CreateNumberText(rootObject.transform, text, new Vector3(0f, outline, 0f), Color.black, damageNumberSize, 60);
// 白色主字最后画(sortingOrder 高),覆盖在黑边之上。
CreateNumberText(rootObject.transform, text, Vector3.zero, Color.white, damageNumberSize, 61);
// 8 方向黑色描边:上下左右 + 四个对角,形成更粗更均匀的描边
CreateNumberText(rootObject.transform, text, new Vector3(-outline, 0f, 0f), Color.black, damageNumberSize, 60); // 左
CreateNumberText(rootObject.transform, text, new Vector3(outline, 0f, 0f), Color.black, damageNumberSize, 60); // 右
CreateNumberText(rootObject.transform, text, new Vector3(0f, -outline, 0f), Color.black, damageNumberSize, 60); // 下
CreateNumberText(rootObject.transform, text, new Vector3(0f, outline, 0f), Color.black, damageNumberSize, 60); // 上
CreateNumberText(rootObject.transform, text, new Vector3(-outline, -outline, 0f), Color.black, damageNumberSize, 60); // 左下
CreateNumberText(rootObject.transform, text, new Vector3(outline, -outline, 0f), Color.black, damageNumberSize, 60); // 右下
CreateNumberText(rootObject.transform, text, new Vector3(-outline, outline, 0f), Color.black, damageNumberSize, 60); // 左上
CreateNumberText(rootObject.transform, text, new Vector3(outline, outline, 0f), Color.black, damageNumberSize, 60); // 右上
// 主字颜色:治疗=绿色,友方受伤=红色,敌方受伤=白色
Color mainColor = isHeal ? Color.green : (isVictimFriend ? Color.red : Color.white);
CreateNumberText(rootObject.transform, text, Vector3.zero, mainColor, damageNumberSize, 61);
DamageNumber number = rootObject.AddComponent<DamageNumber>();
number.duration = damageNumberDuration;
number.riseHeight = damageNumberRiseHeight;
// 友方受伤向下浮动(负值),敌方受伤向上浮动(正值)
number.riseHeight = isVictimFriend ? -damageNumberRiseHeight : damageNumberRiseHeight;
}
// 创建一个配置好的数字 TextMesh 子物体。
@@ -644,7 +670,7 @@ public class DamageNumber : MonoBehaviour
public float duration = 0.8f;
public float riseHeight = 1.2f;
// 一个数字由主字+描边副本共5个TextMesh组成,统一驱动透明度。
// 一个数字由主字 + 8 方向描边副本共 9 个 TextMesh 组成,统一驱动透明度。
private TextMesh[] textMeshes;
private Color[] startColors;
private Vector3 startPosition;