Files
daluandou/Assets/Script/UI脚本/HeroCardUI.cs
T
huadexuan 8d58c2223c 根据提供的code differences信息,由于没有具体的代码变更内容,我将生成一个通用的commit message模板:
```
docs(readme): 更新文档说明

- 添加项目使用指南
- 完善API接口说明
- 修正错误的配置示例
```
2026-10-01 16:01:43 +08:00

305 lines
7.8 KiB
C#

using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 英雄卡片UI控制
/// 显示英雄状态、血条、死亡倒计时、复活按钮
/// </summary>
public class HeroCardUI : MonoBehaviour
{
[Header("引用")]
public Image iconImage; // 英雄头像
public Image hpFillImage; // 血条填充
public GameObject deathPanel; // 死亡遮罩
public Text reviveTimerText; // 复活倒计时文本
public Button reviveButton; // 立即复活按钮(看广告)
public Text reviveCountText; // 剩余复活次数
[Header("绑定的英雄")]
public UnitBase heroUnit; // 关联的英雄单位
private WorldHealthBar heroHealthBar;
private Vector3 heroSpawnPosition; // 英雄出生位置
[Header("复活设置")]
public float reviveTime = 20f; // 自动复活时间
private float reviveTimer = 0f;
private bool isDead = false;
[Header("广告复活次数")]
public int maxAdRevives = 2; // 每局最多2次
private int remainingAdRevives = 2;
private void Start()
{
// 初始化复活次数
remainingAdRevives = maxAdRevives;
UpdateReviveCountUI();
// 绑定复活按钮
if (reviveButton != null)
{
reviveButton.onClick.AddListener(OnReviveButtonClicked);
}
// 默认隐藏死亡面板
if (deathPanel != null)
{
deathPanel.SetActive(false);
}
}
private void Update()
{
if (heroUnit == null || heroHealthBar == null)
{
return;
}
// 更新血条
UpdateHealthBar();
// 检查死亡状态
if (heroHealthBar.IsDead && !isDead)
{
OnHeroDeath();
}
// 检查是否已复活(外部复活,例如通过其他系统)
if (isDead && !heroHealthBar.IsDead && heroUnit.gameObject.activeSelf)
{
// 已复活,重置UI状态
isDead = false;
if (deathPanel != null)
{
deathPanel.SetActive(false);
}
}
// 更新复活倒计时
if (isDead)
{
UpdateReviveTimer();
}
}
/// <summary>
/// 设置英雄单位
/// </summary>
public void SetHero(UnitBase unit, Sprite icon, Vector3 spawnPos)
{
heroUnit = unit;
heroSpawnPosition = spawnPos;
if (unit != null)
{
heroHealthBar = unit.GetComponent<WorldHealthBar>();
}
// 设置头像
if (iconImage != null && icon != null)
{
iconImage.sprite = icon;
}
isDead = false;
if (deathPanel != null)
{
deathPanel.SetActive(false);
}
}
/// <summary>
/// 更新血条显示
/// </summary>
private void UpdateHealthBar()
{
if (hpFillImage != null && heroHealthBar != null)
{
float fillAmount = heroHealthBar.maxHealth > 0
? heroHealthBar.currentHealth / heroHealthBar.maxHealth
: 0f;
hpFillImage.fillAmount = fillAmount;
}
}
/// <summary>
/// 英雄死亡
/// </summary>
private void OnHeroDeath()
{
isDead = true;
reviveTimer = reviveTime;
// 显示死亡面板
if (deathPanel != null)
{
deathPanel.SetActive(true);
}
// 更新复活按钮状态
UpdateReviveButton();
// 阻止英雄单位被销毁(取消延迟销毁)
if (heroUnit != null)
{
// 取消所有Destroy调用
CancelInvoke();
}
Debug.Log($"英雄 {heroUnit.name} 死亡,{reviveTime}秒后复活");
}
/// <summary>
/// 更新复活倒计时
/// </summary>
private void UpdateReviveTimer()
{
reviveTimer -= Time.deltaTime;
// 更新倒计时文本
if (reviveTimerText != null)
{
reviveTimerText.text = Mathf.CeilToInt(reviveTimer).ToString() + "s";
}
// 时间到,自动复活
if (reviveTimer <= 0f)
{
ReviveHero();
}
}
/// <summary>
/// 复活英雄
/// </summary>
private void ReviveHero()
{
if (heroUnit == null || heroHealthBar == null)
{
return;
}
// 重新激活GameObject(必须先激活,否则无法操作组件)
heroUnit.gameObject.SetActive(true);
// 重新启用渲染器
foreach (Renderer renderer in heroUnit.GetComponentsInChildren<Renderer>())
{
renderer.enabled = true;
}
// 移动到出生位置
heroUnit.transform.position = heroSpawnPosition;
// 重置 NavMeshAgent
var navAgent = heroUnit.GetComponent<UnityEngine.AI.NavMeshAgent>();
if (navAgent != null)
{
navAgent.enabled = true; // 确保启用
if (!navAgent.isOnNavMesh)
{
navAgent.enabled = false;
navAgent.enabled = true;
}
navAgent.ResetPath(); // 清空旧路径
}
// 重置 UnitBase 状态(关键修复:清空目标让单位重新寻敌)
UnitBase unitBase = heroUnit.GetComponent<UnitBase>();
if (unitBase != null)
{
unitBase.enabled = true; // 确保脚本启用
unitBase.target = null; // 清空目标
unitBase.ResetAnchorPosition(); // 重置锚点位置到复活位置(修复一直尝试返回旧锚点的问题)
}
// 重置 Animator
Animator animator = heroUnit.GetComponent<Animator>();
if (animator != null)
{
animator.enabled = true;
animator.Rebind(); // 重置动画状态
animator.Update(0f);
}
// 使用WorldHealthBar的Revive方法(会重置isDead并恢复生命)
heroHealthBar.Revive(heroHealthBar.maxHealth);
// 重新显示血条(修复复活后没有血条的问题)
Transform barTransform = heroHealthBar.transform.Find("WorldHealthBar");
if (barTransform != null)
{
barTransform.gameObject.SetActive(true);
}
// 重置UI状态
isDead = false;
if (deathPanel != null)
{
deathPanel.SetActive(false);
}
Debug.Log($"HeroCardUI: {heroUnit.name} 复活完成");
}
/// <summary>
/// 点击立即复活按钮(看广告)
/// </summary>
private void OnReviveButtonClicked()
{
if (remainingAdRevives <= 0)
{
Debug.LogWarning("本局广告复活次数已用完");
return;
}
if (!isDead)
{
return;
}
// TODO: 播放广告
Debug.Log("播放广告...");
// 扣除复活次数
remainingAdRevives--;
UpdateReviveCountUI();
// 立即复活
ReviveHero();
}
/// <summary>
/// 更新复活按钮状态
/// </summary>
private void UpdateReviveButton()
{
if (reviveButton != null)
{
reviveButton.interactable = remainingAdRevives > 0;
}
}
/// <summary>
/// 更新剩余复活次数UI
/// </summary>
private void UpdateReviveCountUI()
{
if (reviveCountText != null)
{
reviveCountText.text = $"复活 {remainingAdRevives}/{maxAdRevives}";
}
UpdateReviveButton();
}
/// <summary>
/// 重置复活次数(新局开始时调用)
/// </summary>
public void ResetReviveCount()
{
remainingAdRevives = maxAdRevives;
UpdateReviveCountUI();
}
}