昨天完成玩家血量機制後,今天開始嘗試製作不同類型的目標。
原本的目標血量只有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];
}
}
}
今天主要完成了以下幾個部分:
目前不同目標已經可以有不同的血量與外觀,接下來預計開始製作分數系統,讓不同目標被擊倒後可以獲得不同的分數。