iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0

昨天完成玩家血量機制後,今天開始嘗試製作不同類型的目標。
原本的目標血量只有1點,所以今天希望讓目標之間可以有不同的血量,並且在受到攻擊後有戰損效果。

修改原本的目標程式

首先修改原本的Mole程式,將currentHp改成protected,讓繼承它的子類別也能夠存取血量。另外將OnHit()加上virtual,之後新的目標就可以重新修改被攻擊時的行為。

using System.Collections;
using UnityEngine;

public class Mole : MonoBehaviour
{
    [Header("地鼠基本屬性")]
    public int maxHp = 1;              
    protected int currentHp;           // 改為 protected,讓子類別存取

    [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;     

    private void Start()
    {
        currentHp = maxHp;
        startPos = transform.position;
        targetPos = startPos + new Vector3(0, riseDistance, 0);

        moleRoutine = StartCoroutine(MoleRoutine());
    }

    private IEnumerator MoleRoutine()
    {
        while (Vector3.Distance(transform.position, targetPos) > 0.01f)
        {
            transform.position = Vector3.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
            yield return null;
        }
        transform.position = targetPos;

        yield return new WaitForSeconds(showDuration);

        while (Vector3.Distance(transform.position, startPos) > 0.01f)
        {
            transform.position = Vector3.MoveTowards(transform.position, startPos, speed * Time.deltaTime);
            yield return null;
        }
        transform.position = startPos;

        if (HealthManager.Instance != null)
        {
            HealthManager.Instance.TakeDamage();
        }

        Destroy(gameObject);
    }

    // 關鍵修改:加上 virtual 關鍵字
    public virtual void OnHit()
    {
        if (isDefeated) return;

        currentHp--;

        if (currentHp <= 0)
        {
            isDefeated = true;

            if (moleRoutine != null)
            {
                StopCoroutine(moleRoutine);
            }

            Debug.Log("成功擊中普通地鼠!");
            Destroy(gameObject);
        }
    }
}

建立新的目標

原先我是想土法煉鋼,一個一個慢慢新增上去。詢問過Gemini,我一開始沒有提到戰損效果,Gemini是提議能用同一個程式碼,只要更改目標的最大血量就好。做到一半發現,假如都用同一個程式碼,沒有做戰損效果,玩家其實很難知道這隻目標目前還剩多少血量。
所以就開始研究如何製作戰損效果,但在哪新增程式碼又顯得奇怪。所以就請教Gemini,得知C#的類別可以繼承另一個類別。
所以我就新增TargetMole,讓它繼承原本的Mole。
新的目標可以設定比較高的血量,並且在受到攻擊後,根據剩餘血量更換圖片,讓玩家可以看到目標受到攻擊後的損傷。

using UnityEngine;

public class TargetMole : Mole
{
    [Header("戰損特效設定")]
    public SpriteRenderer moleRenderer;
    [Tooltip("請依序放入:滿血圖片 ➔ 破損 1 ➔ 破損 2 ➔ 殘破...")]
    public Sprite[] damageSprites; 

    // 重寫 OnHit 邏輯
    public override void OnHit()
    {
        // 呼叫父類別的扣血與死亡判定
        base.OnHit();

        // 如果還沒死亡,根據剩餘血量更換戰損圖片
        if (currentHp > 0)
        {
            UpdateDamageSprite();
        }
    }

    private void UpdateDamageSprite()
    {
        if (moleRenderer == null || damageSprites.Length == 0) return;

        // 計算當前血量對應的圖片索引
        // 例如:maxHp=3, currentHp=2 ➔ 顯示損壞程度 1 的圖片
        int spriteIndex = maxHp - currentHp;

        if (spriteIndex < damageSprites.Length)
        {
            moleRenderer.sprite = damageSprites[spriteIndex];
        }
    }
}

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

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

  • 不同類型的目標:新增TargetMole,讓遊戲中可以出現不同的目標。
  • 繼承功能:新目標可以直接使用原本Mole的移動與血量系統。
  • 不同血量:新目標可以設定比普通目標更高的血量。
  • 戰損效果:受到攻擊後會依照剩餘血量更換圖片。

目前不同目標已經可以有不同的血量與外觀,接下來預計開始製作分數系統,讓不同目標被擊倒後可以獲得不同的分數。


上一篇
Day 20|加入玩家血量與愛心顯示機制
下一篇
Day 22|加入分數與擊殺紀錄
系列文
從基礎到實作:使用 Google AI 學習程式設計 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言