feat(gameplay): 实现护盾系统和强化增益选择机制

- 新增护盾功能,包括护盾数值显示和护盾条UI
- 重构盾卫技能,实现坚固壁垒技能效果
- 添加暴击率、吸血率等战斗属性
- 优化增益选择界面,新增传奇品质和刷新机制
- 调整材质纹理和文字着色器效果
- 修复金币显示格式问题
```
This commit is contained in:
huadexuan committed 2026-10-09 18:13:18 +08:00
1 parent 336ec9980d
commit 48395ab414
27 files changed
+10343 -128

No files matched your search

+94 -11
View File
@@ -10,6 +10,7 @@ public class WorldHealthBar : MonoBehaviour
[Min(0f)] public float currentHealth = 100f;
[Header("护盾")]
public float maxShield = 0f;
public float currentShield = 0f;
/// <summary>
@@ -18,9 +19,32 @@ public class WorldHealthBar : MonoBehaviour
public void AddShield(float amount)
{
if (amount <= 0f || isDead) return;
if (currentShield <= 0f)
{
maxShield = amount;
}
else
{
maxShield += amount;
}
currentShield += amount;
UpdateFill();
Debug.Log($"{gameObject.name} 获得护盾 +{amount:F1},当前护盾: {currentShield:F1}");
UpdateShieldFill();
Debug.Log($"{gameObject.name} 获得护盾 +{amount:F1},当前护盾: {currentShield:F1}/{maxShield:F1}");
}
/// <summary>
/// 减少或清空护盾
/// </summary>
public void RemoveShield(float amount)
{
if (amount <= 0f || currentShield <= 0f) return;
currentShield = Mathf.Max(0f, currentShield - amount);
if (currentShield <= 0f)
{
maxShield = 0f;
}
UpdateShieldFill();
}
// 技能能量上限,英雄默认使用100点;没有技能的小怪可关闭能量条。
@@ -74,7 +98,8 @@ public class WorldHealthBar : MonoBehaviour
// 描边宽度设为私有常量,所有角色统一使用
private const float DamageNumberOutlineWidth = 0.025f; // 从 0.015 增加到 0.025,描边更粗
// 血条 UI 的像素尺寸,实际显示大小由 worldWidth 控制。
// 护盾条高 10 像素,置于血条最上方。
private const int ShieldPixelHeight = 10;
private const int PixelWidth = 100;
private const int PixelHeight = 14;
@@ -82,7 +107,7 @@ public class WorldHealthBar : MonoBehaviour
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;
private const int TotalPixelHeight = ShieldPixelHeight + BarGap + PixelHeight + BarGap + EnergyPixelHeight;
// 世界空间 Canvas,用来承载血条 UI。
private Canvas canvas;
@@ -90,9 +115,17 @@ public class WorldHealthBar : MonoBehaviour
// 血条整体的 RectTransform。
private RectTransform barRect;
// 整体 UI 行节点引用
private RectTransform shieldRow;
private RectTransform healthRow;
private RectTransform energyRow;
// 绿色血量填充 Image。
private Image fillImage;
// 浅蓝色护盾填充 Image。
private Image shieldFillImage;
// 金色技能能量填充 Image。
private Image energyFillImage;
@@ -218,6 +251,7 @@ public class WorldHealthBar : MonoBehaviour
float absorbed = Mathf.Min(currentShield, amount);
currentShield -= absorbed;
amount -= absorbed;
UpdateShieldFill();
Debug.Log($"{gameObject.name} 护盾吸收了 {absorbed:F1} 伤害,剩余护盾: {currentShield:F1}");
}
@@ -472,16 +506,32 @@ public class WorldHealthBar : MonoBehaviour
canvas.sortingOrder = 100;
barObject.GetComponent<CanvasScaler>().dynamicPixelsPerUnit = 10f;
barRect = barObject.GetComponent<RectTransform>();
barRect.sizeDelta = new Vector2(PixelWidth, showEnergyBar ? TotalPixelHeight : PixelHeight);
barRect.sizeDelta = new Vector2(PixelWidth, showEnergyBar ? TotalPixelHeight : (ShieldPixelHeight + PixelHeight));
barRect.localScale = Vector3.one * (worldWidth / PixelWidth);
barRect.localPosition = GetBarRootPosition();
ApplyScaleCompensation();
RectTransform healthRow = CreateRow(barObject.transform, "HealthBar", PixelWidth, PixelHeight, 0);
// 1. 顶层独立护盾条 (ShieldBar)
shieldRow = CreateRow(barObject.transform, "ShieldBar", PixelWidth, ShieldPixelHeight, 0);
Image shieldBackground = CreateImage("ShieldBorder", shieldRow, RoundedSprite(), borderColor); // 加回黑框
SetFullRect(shieldBackground.rectTransform);
Image shieldInner = CreateImage("ShieldFill", shieldRow, RoundedSprite(), new Color(0f, 0.88f, 1f, 0.95f)); // 亮天蓝色
shieldInner.rectTransform.anchorMin = Vector2.zero;
shieldInner.rectTransform.anchorMax = Vector2.one;
shieldInner.rectTransform.offsetMin = new Vector2(2f, 1f);
shieldInner.rectTransform.offsetMax = new Vector2(-2f, -1f);
shieldInner.type = Image.Type.Filled;
shieldInner.fillMethod = Image.FillMethod.Horizontal;
shieldInner.fillOrigin = 0;
shieldFillImage = shieldInner;
shieldRow.gameObject.SetActive(false); // 默认没有护盾时整体收起隐藏
// 2. 中层主血条 (HealthBar)
healthRow = CreateRow(barObject.transform, "HealthBar", PixelWidth, PixelHeight, ShieldPixelHeight + BarGap);
Image background = CreateImage("Border", healthRow, RoundedSprite(), borderColor);
SetFullRect(background.rectTransform);
// 创建填充 Image,颜色暂时使用默认绿色,在 Start() 中根据最终标签设置
Image inner = CreateImage("Fill", healthRow, RoundedSprite(), Color.green);
inner.rectTransform.anchorMin = Vector2.zero;
inner.rectTransform.anchorMax = Vector2.one;
@@ -492,6 +542,7 @@ public class WorldHealthBar : MonoBehaviour
inner.fillOrigin = 0;
fillImage = inner;
// 3. 底层技能能量条 (EnergyBar)
if (!showEnergyBar)
{
energyFillImage = null;
@@ -499,12 +550,12 @@ public class WorldHealthBar : MonoBehaviour
return;
}
RectTransform energyRow = CreateRow(
energyRow = CreateRow(
barObject.transform,
"EnergyBar",
EnergyPixelWidth,
EnergyPixelHeight,
PixelHeight + BarGap);
ShieldPixelHeight + BarGap + PixelHeight + BarGap);
Image energyBackground = CreateImage("EnergyBorder", energyRow, RoundedSprite(), borderColor);
SetFullRect(energyBackground.rectTransform);
@@ -619,7 +670,7 @@ public class WorldHealthBar : MonoBehaviour
// 创建血条左侧的圆圈等级徽章
private void CreateLevelBadge(Transform parent)
{
int badgeSize = 26; // 圆圈徽章直径
int badgeSize = 39; // 调整为原来的 1.5 倍 (从 26 增大至 39)
GameObject badgeObj = new GameObject("LevelBadge", typeof(RectTransform));
badgeObj.transform.SetParent(parent, false);
@@ -628,7 +679,7 @@ public class WorldHealthBar : MonoBehaviour
badgeRect.anchorMax = new Vector2(0f, 1f);
badgeRect.pivot = new Vector2(1f, 0.5f); // 右边缘切齐,紧贴血条左边缘
badgeRect.sizeDelta = new Vector2(badgeSize, badgeSize);
badgeRect.anchoredPosition = new Vector2(2f, -PixelHeight * 0.5f); // 总是对齐第一行血条中心
badgeRect.anchoredPosition = new Vector2(2f, -15f); // 居中对齐主血条中心 (posY = -15f)
// 外层黑边圆圈
Image outerCircle = CreateImage("OuterCircle", badgeRect, CircleSprite(), new Color(0.05f, 0.05f, 0.05f, 0.95f));
@@ -652,7 +703,7 @@ public class WorldHealthBar : MonoBehaviour
levelText = textObj.GetComponent<Text>();
levelText.text = unitLevel.ToString();
levelText.font = GetBuiltinFont();
levelText.fontSize = 18;
levelText.fontSize = 26; // 字体同步放大
levelText.fontStyle = FontStyle.Bold;
levelText.alignment = TextAnchor.MiddleCenter;
levelText.color = new Color(0.95f, 0.98f, 0.95f, 1f);
@@ -701,6 +752,38 @@ public class WorldHealthBar : MonoBehaviour
}
}
// 根据当前护盾值更新天蓝色填充比例与显隐。
private void UpdateShieldFill()
{
if (shieldRow != null && shieldFillImage != null)
{
if (currentShield > 0f)
{
shieldRow.gameObject.SetActive(true);
// 1. 护盾条左对齐:锚点改为左上角
shieldRow.anchorMin = new Vector2(0f, 1f);
shieldRow.anchorMax = new Vector2(0f, 1f);
shieldRow.pivot = new Vector2(0f, 1f);
shieldRow.anchoredPosition = new Vector2(0f, 0f);
// 2. 护盾条的物理宽度按 (maxShield / maxHealth) 比例,代表护盾容量占血条的比例
float shieldRatio = maxHealth > 0f ? Mathf.Clamp01(maxShield / maxHealth) : 1.0f;
float targetWidth = PixelWidth * Mathf.Max(0.05f, shieldRatio);
shieldRow.sizeDelta = new Vector2(targetWidth, ShieldPixelHeight);
// 3. 天蓝色填充条按 (currentShield / maxShield) 动态扣减
float fillRatio = maxShield > 0f ? Mathf.Clamp01(currentShield / maxShield) : 1.0f;
shieldFillImage.fillAmount = fillRatio;
shieldFillImage.SetVerticesDirty();
}
else
{
shieldRow.gameObject.SetActive(false);
}
}
}
// 创建并缓存一个直角矩形白色 Sprite,供边框和填充复用。
private static Sprite RoundedSprite()
{