```
feat(WorldHealthBar): 添加技能能量系统并重构血条UI布局 - 新增技能能量相关属性(maxEnergy、currentEnergy) - 添加能量条UI组件和布局管理 - 实现AddEnergy和ResetEnergy方法支持能量管理 - 调整血条整体布局以容纳能量条 - 移除已废弃的EnemyBaseMove脚本及其元文件 ```
This commit is contained in:
1 parent
98176721d0
commit
e532a6c8ce
24 files changed
+7525
-6
No files matched your search
@@ -9,6 +9,13 @@ public class WorldHealthBar : MonoBehaviour
|
||||
// 当前生命值,范围会自动限制在 0 到 maxHealth 之间。
|
||||
[Min(0f)] public float currentHealth = 100f;
|
||||
|
||||
// 技能能量上限,所有单位默认使用100点。
|
||||
[Header("技能能量")]
|
||||
[Min(1f)] public float maxEnergy = 100f;
|
||||
|
||||
// 当前技能能量,范围会自动限制在 0 到 maxEnergy 之间。
|
||||
[Min(0f)] public float currentEnergy = 0f;
|
||||
|
||||
// 血条相对于单位头顶的额外高度。
|
||||
[Min(0f)] public float heightOffset = 0.25f;
|
||||
|
||||
@@ -28,6 +35,12 @@ public class WorldHealthBar : MonoBehaviour
|
||||
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 TotalPixelHeight = PixelHeight + BarGap + EnergyPixelHeight;
|
||||
|
||||
// 世界空间 Canvas,用来承载血条 UI。
|
||||
private Canvas canvas;
|
||||
|
||||
@@ -37,6 +50,9 @@ public class WorldHealthBar : MonoBehaviour
|
||||
// 绿色血量填充 Image。
|
||||
private Image fillImage;
|
||||
|
||||
// 金色技能能量填充 Image。
|
||||
private Image energyFillImage;
|
||||
|
||||
// 血条相对于单位的本地位置。
|
||||
private Vector3 localBarPosition;
|
||||
|
||||
@@ -54,16 +70,19 @@ 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);
|
||||
CalculateLayout();
|
||||
CreateBar();
|
||||
UpdateFill();
|
||||
UpdateEnergyFill();
|
||||
}
|
||||
|
||||
// 每帧让血条保持在单位头顶,并朝向主摄像机。
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (barRect == null) return;
|
||||
barRect.localPosition = localBarPosition;
|
||||
barRect.localPosition = GetBarRootPosition();
|
||||
|
||||
// 优先使用场景中名称完全为 Main Camera 的摄像机。
|
||||
Camera camera = FindMainCamera();
|
||||
@@ -121,6 +140,32 @@ public class WorldHealthBar : MonoBehaviour
|
||||
// 让单位恢复生命值。
|
||||
public void Heal(float amount) => SetHealth(currentHealth + amount);
|
||||
|
||||
// 增加技能能量,并返回本次增加后是否达到满能量。
|
||||
public bool AddEnergy(float amount)
|
||||
{
|
||||
if (isDead || amount <= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float previousEnergy = currentEnergy;
|
||||
currentEnergy = Mathf.Clamp(currentEnergy + amount, 0f, maxEnergy);
|
||||
UpdateEnergyFill();
|
||||
return previousEnergy < maxEnergy && currentEnergy >= maxEnergy;
|
||||
}
|
||||
|
||||
// 清空技能能量并刷新能量条。
|
||||
public void ResetEnergy()
|
||||
{
|
||||
if (isDead)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentEnergy = 0f;
|
||||
UpdateEnergyFill();
|
||||
}
|
||||
|
||||
// 处理单位死亡:隐藏模型和血条,播放蓝色向上爆散特效。
|
||||
private void Die()
|
||||
{
|
||||
@@ -284,14 +329,15 @@ public class WorldHealthBar : MonoBehaviour
|
||||
canvas.sortingOrder = 100;
|
||||
barObject.GetComponent<CanvasScaler>().dynamicPixelsPerUnit = 10f;
|
||||
barRect = barObject.GetComponent<RectTransform>();
|
||||
barRect.sizeDelta = new Vector2(PixelWidth, PixelHeight);
|
||||
barRect.sizeDelta = new Vector2(PixelWidth, TotalPixelHeight);
|
||||
barRect.localScale = Vector3.one * (worldWidth / PixelWidth);
|
||||
barRect.localPosition = localBarPosition;
|
||||
barRect.localPosition = GetBarRootPosition();
|
||||
|
||||
Image background = CreateImage("Border", barObject.transform, RoundedSprite(), borderColor);
|
||||
RectTransform healthRow = CreateRow(barObject.transform, "HealthBar", PixelWidth, PixelHeight, 0);
|
||||
Image background = CreateImage("Border", healthRow, RoundedSprite(), borderColor);
|
||||
SetFullRect(background.rectTransform);
|
||||
|
||||
Image inner = CreateImage("Fill", barObject.transform, RoundedSprite(), GetHealthFillColor());
|
||||
Image inner = CreateImage("Fill", healthRow, RoundedSprite(), GetHealthFillColor());
|
||||
inner.rectTransform.anchorMin = Vector2.zero;
|
||||
inner.rectTransform.anchorMax = Vector2.one;
|
||||
inner.rectTransform.offsetMin = new Vector2(2f, 2f);
|
||||
@@ -300,6 +346,57 @@ public class WorldHealthBar : MonoBehaviour
|
||||
inner.fillMethod = Image.FillMethod.Horizontal;
|
||||
inner.fillOrigin = 0;
|
||||
fillImage = inner;
|
||||
|
||||
RectTransform energyRow = CreateRow(
|
||||
barObject.transform,
|
||||
"EnergyBar",
|
||||
EnergyPixelWidth,
|
||||
EnergyPixelHeight,
|
||||
PixelHeight + BarGap);
|
||||
Image energyBackground = CreateImage("EnergyBorder", energyRow, RoundedSprite(), borderColor);
|
||||
SetFullRect(energyBackground.rectTransform);
|
||||
|
||||
Image energyInner = CreateImage(
|
||||
"EnergyFill",
|
||||
energyRow,
|
||||
RoundedSprite(),
|
||||
GetEnergyFillColor());
|
||||
energyInner.rectTransform.anchorMin = Vector2.zero;
|
||||
energyInner.rectTransform.anchorMax = Vector2.one;
|
||||
energyInner.rectTransform.offsetMin = new Vector2(2f, 1f);
|
||||
energyInner.rectTransform.offsetMax = new Vector2(-2f, -1f);
|
||||
energyInner.type = Image.Type.Filled;
|
||||
energyInner.fillMethod = Image.FillMethod.Horizontal;
|
||||
energyInner.fillOrigin = 0;
|
||||
energyFillImage = energyInner;
|
||||
}
|
||||
|
||||
// 返回整体 Canvas 的位置,使血条中心保持原来的高度。
|
||||
private Vector3 GetBarRootPosition()
|
||||
{
|
||||
float pixelToWorld = worldWidth / PixelWidth;
|
||||
float energyOffset = (TotalPixelHeight - PixelHeight) * 0.5f * pixelToWorld;
|
||||
return localBarPosition - Vector3.up * energyOffset;
|
||||
}
|
||||
|
||||
// 创建一行固定像素高度的世界空间 UI。
|
||||
private static RectTransform CreateRow(
|
||||
Transform parent,
|
||||
string name,
|
||||
int width,
|
||||
int height,
|
||||
int topOffset)
|
||||
{
|
||||
GameObject rowObject = new GameObject(name, typeof(RectTransform));
|
||||
rowObject.transform.SetParent(parent, false);
|
||||
|
||||
RectTransform rowRect = rowObject.GetComponent<RectTransform>();
|
||||
rowRect.anchorMin = new Vector2(0.5f, 1f);
|
||||
rowRect.anchorMax = new Vector2(0.5f, 1f);
|
||||
rowRect.pivot = new Vector2(0.5f, 1f);
|
||||
rowRect.sizeDelta = new Vector2(width, height);
|
||||
rowRect.anchoredPosition = new Vector2(0f, -topOffset);
|
||||
return rowRect;
|
||||
}
|
||||
|
||||
private Color GetHealthFillColor()
|
||||
@@ -309,6 +406,11 @@ public class WorldHealthBar : MonoBehaviour
|
||||
: new Color(0.1f, 0.8f, 0.18f, 1f);
|
||||
}
|
||||
|
||||
private Color GetEnergyFillColor()
|
||||
{
|
||||
return new Color(1f, 0.72f, 0.08f, 1f);
|
||||
}
|
||||
|
||||
// 创建一个用于边框或填充的 UI Image。
|
||||
private static Image CreateImage(string name, Transform parent, Sprite sprite, Color color)
|
||||
{
|
||||
@@ -338,6 +440,15 @@ public class WorldHealthBar : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// 根据当前技能能量更新金色填充比例。
|
||||
private void UpdateEnergyFill()
|
||||
{
|
||||
if (energyFillImage != null)
|
||||
{
|
||||
energyFillImage.fillAmount = Mathf.Clamp01(currentEnergy / maxEnergy);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建并缓存一个带圆角的白色 Sprite,供边框和填充复用。
|
||||
private static Sprite RoundedSprite()
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user