305 lines
7.8 KiB
C#
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();
|
|
}
|
|
}
|