昨天完成了目標的移動與玩家點擊判定,今天則繼續加入玩家血量機制。
這次使用三顆愛心代表玩家的生命值,當目標沒有被成功擊中,並完整縮回土堆時,就會扣除玩家一點血量。當血量歸零時,則會觸發遊戲結束的判定。
首先,修改原本的Mole程式,新增Coroutine參考,用來記錄目標的移動流程。
當玩家成功擊中目標時,會立刻停止Coroutine並銷毀物件,避免目標被擊中後,仍然執行縮回土堆的扣血流程。
using System.Collections;
using UnityEngine;
public class Mole : MonoBehaviour
{
[Header("地鼠基本屬性")]
public int maxHp = 1; // 最大血量
private int currentHp;
[Header("移動與時間設定")]
public float riseDistance = 1.2f; // 向上冒出的距離
public float speed = 5f; // 升降速度
public float showDuration = 1.0f; // 露頭停留時間
private Vector3 startPos;
private Vector3 targetPos;
private bool isDefeated = false; // 是否已被玩家打倒
private Coroutine moleRoutine; // 儲存 Coroutine 的參考
private void Start()
{
currentHp = maxHp;
startPos = transform.position;
targetPos = startPos + new Vector3(0, riseDistance, 0);
// 啟動並記錄 Coroutine
moleRoutine = StartCoroutine(MoleRoutine());
}
private IEnumerator MoleRoutine()
{
// 1. 往上升起
while (Vector3.Distance(transform.position, targetPos) > 0.01f)
{
transform.position = Vector3.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
yield return null;
}
transform.position = targetPos;
// 2. 停留等待玩家打擊
yield return new WaitForSeconds(showDuration);
// 3. 往下滑回土堆
while (Vector3.Distance(transform.position, startPos) > 0.01f)
{
transform.position = Vector3.MoveTowards(transform.position, startPos, speed * Time.deltaTime);
yield return null;
}
transform.position = startPos;
// 4. 到這裡代表已經完整縮回土裡,且未被打倒 ➔ 執行扣血
if (HealthManager.Instance != null)
{
HealthManager.Instance.TakeDamage();
}
// 5. 銷毀地鼠物件
Destroy(gameObject);
}
// 玩家點擊時呼叫
public void OnHit()
{
if (isDefeated) return;
currentHp--;
if (currentHp <= 0)
{
isDefeated = true;
// 關鍵修改:擊中時立刻終止縮回與扣血的 Coroutine
if (moleRoutine != null)
{
StopCoroutine(moleRoutine);
}
Debug.Log("成功擊中地鼠!");
// 立刻銷毀地鼠(不會再執行到扣血程式碼)
Destroy(gameObject);
}
}
}
接著新增HealthManager,統一管理玩家的血量與愛心顯示。
目前玩家初始血量為三點,透過TakeDamage()扣除生命值,再由UpdateHeartsUI()更新畫面上的亮愛心。當血量歸零時,就會呼叫 GameOver()。
using UnityEngine;
using UnityEngine.UI;
public class HealthManager : MonoBehaviour
{
public static HealthManager Instance;
[Header("血量設定")]
public int currentHealth = 3; // 當前血量
[Tooltip("請拉入疊在上面、代表亮愛心的 Image")]
public Image[] fullHearts; // 上層的 3 個亮愛心 Image
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
else
{
Destroy(gameObject);
}
}
private void Start()
{
UpdateHeartsUI();
}
// 扣血方法
public void TakeDamage()
{
if (currentHealth <= 0) return;
currentHealth--;
UpdateHeartsUI();
if (currentHealth <= 0)
{
GameOver();
}
}
// 更新亮愛心的顯示狀態
private void UpdateHeartsUI()
{
for (int i = 0; i < fullHearts.Length; i++)
{
// 只要索引小於當前血量就顯示,否則直接關閉顯示
if (i < currentHealth)
{
fullHearts[i].enabled = true; // 顯示亮愛心
}
else
{
fullHearts[i].enabled = false; // 隱藏亮愛心,露出底下的暗愛心
}
}
}
private void GameOver()
{
Debug.Log("Game Over! 玩家血量歸零,遊戲結束!");
}
}
今天主要完成了以下幾個部分:
接下來預計會做不同的目標,Mole目前生成的目標血量都只有1點,我應該會嘗試去增加不同的目標,讓他們有不同的血量,之後做分數系統也能因不同目標而有不同的分數。