昨天完成了目標的生成系統,今天則繼續製作目標的移動與玩家攻擊判定。
這次希望目標不只是出現在洞口,而是能夠從土堆中冒出來,停留一段時間後再縮回去。如果玩家在這段時間內成功點擊目標,就會直接擊敗地鼠。
這次建立了Mole,負責控制目標的升降、停留時間,以及受到攻擊後的血量判定。
using System.Collections;
using UnityEngine;
public class Mole : MonoBehaviour
{
[Header("地鼠基本屬性")]
public int maxHp = 1; // 最大血量(第一種目標為 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 void Start()
{
currentHp = maxHp;
startPos = transform.position;
targetPos = startPos + new Vector3(0, riseDistance, 0);
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. 自然縮回後直接銷毀
Destroy(gameObject);
}
// 玩家點擊時呼叫
public void OnHit()
{
if (isDefeated) return;
currentHp--;
if (currentHp <= 0)
{
isDefeated = true;
Debug.Log("擊中地鼠!");
// 可以在這裡加入打擊音效或消失特效
Destroy(gameObject);
}
}
}
這裡使用 Coroutine 控制地鼠的移動流程,並透過Vector3.MoveTowards()讓目標逐漸升起與縮回。玩家成功擊中地鼠後,則會扣除血量,當血量歸零時就會將目標銷毀。
接著建立PlayerClicker,負責偵測玩家的滑鼠或手機觸控,並利用2D射線判斷是否點擊到目標。
using UnityEngine;
public class PlayerClicker : MonoBehaviour
{
private void Update()
{
// 1. 處理電腦滑鼠點擊
if (Input.GetMouseButtonDown(0))
{
CheckHit(Input.mousePosition);
}
// 2. 處理手機多點觸控(Touch)
if (Input.touchCount > 0)
{
foreach (Touch touch in Input.touches)
{
// 當手指剛接觸螢幕的瞬間(Began)
if (touch.phase == TouchPhase.Began)
{
CheckHit(touch.position);
}
}
}
}
// 統一進行 2D 射線點擊判斷
private void CheckHit(Vector3 screenPosition)
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(screenPosition);
Vector2 mousePos2D = new Vector2(mousePos.x, mousePos.y);
// 射出 2D 射線檢測是否擊中地鼠
RaycastHit2D hit = Physics2D.Raycast(mousePos2D, Vector2.zero);
if (hit.collider != null)
{
Mole mole = hit.collider.GetComponent<Mole>();
if (mole != null)
{
mole.OnHit();
}
}
}
}
這段程式碼會在玩家點擊螢幕時進行碰撞判定。如果成功點擊到具有Collider2D的地鼠,就會呼叫OnHit(),讓地鼠執行受擊判定。
今天完成了目標的升降、停留、受擊判定,以及玩家的點擊偵測。
目前玩家成功擊中目標後,目標就會消失;如果沒有擊中,目標則會在停留一段時間後縮回洞口。
接下來預計製作玩家血量機制,讓目標逃走時會影響玩家的生命值,逐步增加遊戲的挑戰性,再來製作多種目標,會因目標不同會有不同受擊次數。