iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
Build on Google AI

從基礎到實作:使用 Google AI 學習程式設計系列 第 20 篇

Day 20|加入玩家血量與愛心顯示機制

  • 分享至 

  • xImage
  •  

昨天完成了目標的移動與玩家點擊判定,今天則繼續加入玩家血量機制。
這次使用三顆愛心代表玩家的生命值,當目標沒有被成功擊中,並完整縮回土堆時,就會扣除玩家一點血量。當血量歸零時,則會觸發遊戲結束的判定。

修改目標的移動與扣血機制

首先,修改原本的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! 玩家血量歸零,遊戲結束!");
    }
}

第二十天的成果與之後目標

今天主要完成了以下幾個部分:

  • 目標與血量連動:目標成功縮回土堆時,玩家會扣除一點血量。
  • 愛心顯示:透過UI Image控制亮愛心的顯示,讓玩家能直接看到剩餘生命值。
  • 避免重複扣血:成功擊中目標時,停止移動流程,避免後續又觸發扣血。
  • 遊戲結束判定:當玩家血量歸零時,呼叫GameOver()。

接下來預計會做不同的目標,Mole目前生成的目標血量都只有1點,我應該會嘗試去增加不同的目標,讓他們有不同的血量,之後做分數系統也能因不同目標而有不同的分數。


上一篇
Day 19|讓目標動起來並偵測玩家攻擊
下一篇
Day 21|製作不同類型的目標
系列文
從基礎到實作:使用 Google AI 學習程式設計 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言