```
feat(gameplay): 提升单位检测范围并添加法师属性 - 将所有单位的检测范围从默认值提升至100 - 为法师预制体添加护盾、等级等新属性 - 为法师添加暴击、吸血、伤害减免等战斗属性 - 更换法师弹丸预设并调整相关参数 - 添加锚点交战Z线控制功能 - 更新玩家数据中配备的召唤师技能 - 移除多余的纹理配置文件 ```
This commit is contained in:
1 parent
6089308f66
commit
23c559d9f7
243 files changed
+150612
-1459
No files matched your search
@@ -9,6 +9,20 @@ public class WorldHealthBar : MonoBehaviour
|
||||
// 当前生命值,范围会自动限制在 0 到 maxHealth 之间。
|
||||
[Min(0f)] public float currentHealth = 100f;
|
||||
|
||||
[Header("护盾")]
|
||||
public float currentShield = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// 为单位添加护盾
|
||||
/// </summary>
|
||||
public void AddShield(float amount)
|
||||
{
|
||||
if (amount <= 0f || isDead) return;
|
||||
currentShield += amount;
|
||||
UpdateFill();
|
||||
Debug.Log($"{gameObject.name} 获得护盾 +{amount:F1},当前护盾: {currentShield:F1}");
|
||||
}
|
||||
|
||||
// 技能能量上限,英雄默认使用100点;没有技能的小怪可关闭能量条。
|
||||
[Header("技能能量")]
|
||||
public bool showEnergyBar = true;
|
||||
@@ -88,8 +102,14 @@ public class WorldHealthBar : MonoBehaviour
|
||||
// 血条最终使用的世界宽度。
|
||||
private float worldWidth;
|
||||
|
||||
// 所有血条共用的圆角 Sprite。
|
||||
[Header("等级显示")]
|
||||
public int unitLevel = 1;
|
||||
|
||||
// 所有血条共用的圆角 Sprite 和圆形 Sprite。
|
||||
private static Sprite roundedSprite;
|
||||
private static Sprite circleSprite;
|
||||
private Text levelText;
|
||||
private Image levelBadgeBg;
|
||||
|
||||
// 防止死亡逻辑重复执行。
|
||||
private bool isDead;
|
||||
@@ -97,6 +117,15 @@ public class WorldHealthBar : MonoBehaviour
|
||||
// 公开死亡状态供外部查询(用于胜负判定)
|
||||
public bool IsDead => isDead;
|
||||
|
||||
public void SetLevel(int level)
|
||||
{
|
||||
unitLevel = Mathf.Max(1, level);
|
||||
if (levelText != null)
|
||||
{
|
||||
levelText.text = unitLevel.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化血量和血条 UI。
|
||||
private void Awake()
|
||||
{
|
||||
@@ -133,16 +162,16 @@ public class WorldHealthBar : MonoBehaviour
|
||||
canvas.worldCamera = camera;
|
||||
if (camera.gameObject.name == "Main Camera")
|
||||
{
|
||||
// 使用摄像机的上方向,保证血条在摄像机画面中保持水平。
|
||||
// 面向摄像机背面,保证 UI 左右方向不发生镜像反转
|
||||
barRect.rotation = Quaternion.LookRotation(
|
||||
camera.transform.position - barRect.position,
|
||||
barRect.position - camera.transform.position,
|
||||
camera.transform.up);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 找不到 Main Camera 时,保留原来的展示逻辑。
|
||||
barRect.rotation = Quaternion.LookRotation(
|
||||
camera.transform.position - barRect.position,
|
||||
barRect.position - camera.transform.position,
|
||||
Vector3.up);
|
||||
}
|
||||
}
|
||||
@@ -181,12 +210,27 @@ public class WorldHealthBar : MonoBehaviour
|
||||
public void TakeDamage(float amount, GameObject attacker = null)
|
||||
{
|
||||
bool wasDead = isDead;
|
||||
SetHealth(currentHealth - amount);
|
||||
if (showDamageNumbers && amount > 0f && !wasDead)
|
||||
float originalDamage = amount;
|
||||
|
||||
// 优先消耗护盾抵扣伤害
|
||||
if (currentShield > 0f && amount > 0f)
|
||||
{
|
||||
float absorbed = Mathf.Min(currentShield, amount);
|
||||
currentShield -= absorbed;
|
||||
amount -= absorbed;
|
||||
Debug.Log($"{gameObject.name} 护盾吸收了 {absorbed:F1} 伤害,剩余护盾: {currentShield:F1}");
|
||||
}
|
||||
|
||||
if (amount > 0f)
|
||||
{
|
||||
SetHealth(currentHealth - amount);
|
||||
}
|
||||
|
||||
if (showDamageNumbers && originalDamage > 0f && !wasDead)
|
||||
{
|
||||
// 判断受击者(自己)是否是友方(Friend tag)
|
||||
bool isVictimFriend = gameObject.CompareTag("Friend");
|
||||
SpawnDamageNumber(amount, false, isVictimFriend);
|
||||
SpawnDamageNumber(originalDamage, false, isVictimFriend);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,6 +495,7 @@ public class WorldHealthBar : MonoBehaviour
|
||||
if (!showEnergyBar)
|
||||
{
|
||||
energyFillImage = null;
|
||||
CreateLevelBadge(barObject.transform);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -476,6 +521,8 @@ public class WorldHealthBar : MonoBehaviour
|
||||
energyInner.fillMethod = Image.FillMethod.Horizontal;
|
||||
energyInner.fillOrigin = 0;
|
||||
energyFillImage = energyInner;
|
||||
|
||||
CreateLevelBadge(barObject.transform);
|
||||
}
|
||||
|
||||
private void ApplyScaleCompensation()
|
||||
@@ -539,6 +586,83 @@ public class WorldHealthBar : MonoBehaviour
|
||||
return new Color(1f, 0.72f, 0.08f, 1f);
|
||||
}
|
||||
|
||||
// 创建圆形 Sprite 用于等级徽章背景。
|
||||
private static Sprite CircleSprite()
|
||||
{
|
||||
if (circleSprite != null) return circleSprite;
|
||||
|
||||
Texture2D texture = new Texture2D(64, 64, TextureFormat.RGBA32, false);
|
||||
float radius = 30f;
|
||||
Vector2 center = new Vector2(31.5f, 31.5f);
|
||||
|
||||
for (int y = 0; y < 64; y++)
|
||||
{
|
||||
for (int x = 0; x < 64; x++)
|
||||
{
|
||||
float dist = Vector2.Distance(new Vector2(x, y), center);
|
||||
if (dist > radius)
|
||||
{
|
||||
texture.SetPixel(x, y, Color.clear);
|
||||
}
|
||||
else
|
||||
{
|
||||
float alpha = Mathf.Clamp01(radius + 0.5f - dist);
|
||||
texture.SetPixel(x, y, new Color(1f, 1f, 1f, alpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
texture.Apply();
|
||||
circleSprite = Sprite.Create(texture, new Rect(0, 0, 64, 64), new Vector2(0.5f, 0.5f));
|
||||
return circleSprite;
|
||||
}
|
||||
|
||||
// 创建血条左侧的圆圈等级徽章
|
||||
private void CreateLevelBadge(Transform parent)
|
||||
{
|
||||
int badgeSize = 26; // 圆圈徽章直径
|
||||
GameObject badgeObj = new GameObject("LevelBadge", typeof(RectTransform));
|
||||
badgeObj.transform.SetParent(parent, false);
|
||||
|
||||
RectTransform badgeRect = badgeObj.GetComponent<RectTransform>();
|
||||
badgeRect.anchorMin = new Vector2(0f, 1f);
|
||||
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); // 总是对齐第一行血条中心
|
||||
|
||||
// 外层黑边圆圈
|
||||
Image outerCircle = CreateImage("OuterCircle", badgeRect, CircleSprite(), new Color(0.05f, 0.05f, 0.05f, 0.95f));
|
||||
SetFullRect(outerCircle.rectTransform);
|
||||
|
||||
// 内层深色底板
|
||||
Image innerCircle = CreateImage("InnerCircle", outerCircle.transform, CircleSprite(), new Color(0.12f, 0.18f, 0.15f, 1f));
|
||||
innerCircle.rectTransform.anchorMin = Vector2.zero;
|
||||
innerCircle.rectTransform.anchorMax = Vector2.one;
|
||||
innerCircle.rectTransform.offsetMin = new Vector2(2f, 2f);
|
||||
innerCircle.rectTransform.offsetMax = new Vector2(-2f, -2f);
|
||||
levelBadgeBg = innerCircle;
|
||||
|
||||
// 居中阿拉伯数字 Text
|
||||
GameObject textObj = new GameObject("LevelText", typeof(RectTransform), typeof(Text));
|
||||
textObj.transform.SetParent(innerCircle.transform, false);
|
||||
|
||||
RectTransform textRect = textObj.GetComponent<RectTransform>();
|
||||
SetFullRect(textRect);
|
||||
|
||||
levelText = textObj.GetComponent<Text>();
|
||||
levelText.text = unitLevel.ToString();
|
||||
levelText.font = GetBuiltinFont();
|
||||
levelText.fontSize = 18;
|
||||
levelText.fontStyle = FontStyle.Bold;
|
||||
levelText.alignment = TextAnchor.MiddleCenter;
|
||||
levelText.color = new Color(0.95f, 0.98f, 0.95f, 1f);
|
||||
|
||||
// 加上外发光/描边效果
|
||||
var shadow = textObj.AddComponent<Shadow>();
|
||||
shadow.effectColor = new Color(0f, 0f, 0f, 0.9f);
|
||||
shadow.effectDistance = new Vector2(1f, -1f);
|
||||
}
|
||||
|
||||
// 创建一个用于边框或填充的 UI Image。
|
||||
private static Image CreateImage(string name, Transform parent, Sprite sprite, Color color)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user