昨天已經完成羽毛收集與技能按鈕的連動,收集三根羽毛後,技能按鈕會從灰色圖片替換成亮色圖片。
今天就繼續往下一步製作,讓這個技能真正有作用。
原本的構想是讓鳥在使用技能後可以暫時無視障礙物,所以這次先讓技能具備「無敵穿透」的效果。
目前希望技能可以做到:
這次請 Gemini 協助修改原本的 BirdController,把前幾天完成的羽毛收集、技能按鈕和新的技能效果整合在一起。
其中增加了 isInvincible 來判斷目前是否處於無敵狀態,並設定技能持續時間,預設為 3 秒。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class BirdController : MonoBehaviour
{
[Header("物理與跳躍設定")]
[Tooltip("跳躍力道")]
public float jumpForce = 6f;
[Tooltip("重力大小(預設 2.5,數值越大掉落越快)")]
public float gravityScale = 2.5f;
private Rigidbody2D rb;
private SpriteRenderer spriteRenderer; // 用於控制技能發動時的透明度視覺
private bool isDead = false;
[Header("羽毛 UI 圖片設定")]
[Tooltip("將左上角的 3 個 UI Image 依序拉進來")]
public Image[] featherUIImages;
[Tooltip("暗色羽毛 Sprite")]
public Sprite featherDarkSprite;
[Tooltip("亮色羽毛 Sprite")]
public Sprite featherLightSprite;
[Header("技能按鈕 UI 設定")]
public Button skillButton;
public Image skillButtonImage;
public Sprite skillDisabledSprite; // 灰色技能按鈕
public Sprite skillReadySprite; // 亮色技能按鈕
[Header("目前收集進度")]
public int currentFeathers = 0;
public int maxFeathers = 3;
public bool isSkillReady = false;
[Header("技能設定(無敵穿透)")]
[Tooltip("技能持續時間(秒)")]
public float skillDuration = 3f;
[Tooltip("技能發動中(無敵狀態,無視岩石地面碰撞)")]
public bool isInvincible = false;
void Start()
{
rb = GetComponent<Rigidbody2D>();
spriteRenderer = GetComponent<SpriteRenderer>(); // 取得 SpriteRenderer
// 套用自訂重力數值
if (rb != null)
{
rb.gravityScale = gravityScale;
}
if (skillButton != null && skillButtonImage == null)
{
skillButtonImage = skillButton.GetComponent<Image>();
}
// 初始化:羽毛全暗、技能灰色
ResetFeathersUI();
SetSkillReady(false);
}
void Update()
{
if (isDead) return;
// 防範 UI 穿透點擊(點擊右下角技能鍵時不觸發背景普通跳躍)
if (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject())
{
return;
}
bool isComputerInput = Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0);
bool isMobileInput = Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began;
if (isComputerInput || isMobileInput)
{
Jump();
}
}
void Jump()
{
if (isDead) return;
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
private void OnCollisionEnter2D(Collision2D collision)
{
// 【核心修改】若處於技能無敵狀態,無視岩石與地面的死亡碰撞!
if (isInvincible) return;
if (collision.gameObject.CompareTag("Rock") || collision.gameObject.CompareTag("Ground"))
{
Die();
}
}
void Die()
{
isDead = true;
Debug.Log("小鳥撞到了!遊戲結束。");
}
// 觸發碰撞檢測:吃到羽毛道具(完全不受無敵影響,仍然可以正常收集)
private void OnTriggerEnter2D(Collider2D collision)
{
if (isDead) return;
if (collision.CompareTag("Feather") || collision.CompareTag("Item"))
{
CollectFeather();
Destroy(collision.gameObject);
}
}
public void CollectFeather()
{
if (currentFeathers < maxFeathers)
{
currentFeathers++;
UpdateFeathersUI();
if (currentFeathers >= maxFeathers)
{
SetSkillReady(true);
}
}
}
void UpdateFeathersUI()
{
if (featherUIImages == null) return;
for (int i = 0; i < featherUIImages.Length; i++)
{
if (featherUIImages[i] == null) continue;
if (i < currentFeathers)
{
featherUIImages[i].sprite = featherLightSprite;
}
else
{
featherUIImages[i].sprite = featherDarkSprite;
}
}
}
void ResetFeathersUI()
{
currentFeathers = 0;
UpdateFeathersUI();
}
void SetSkillReady(bool ready)
{
isSkillReady = ready;
if (skillButtonImage != null)
{
skillButtonImage.sprite = ready ? skillReadySprite : skillDisabledSprite;
}
if (skillButton != null)
{
skillButton.interactable = true;
}
}
// 點擊右下角技能圖示時觸發
public void OnSkillButtonClick()
{
if (isDead) return;
if (isSkillReady && !isInvincible)
{
UseSkill();
}
else
{
Jump(); // 技能未就緒時,點擊依然進行普通跳躍
}
}
// 釋放技能邏輯
void UseSkill()
{
Debug.Log("釋放技能:開啟無敵穿透!");
// 消耗羽毛進度與重置技能 UI
ResetFeathersUI();
SetSkillReady(false);
// 啟動無敵協程
StartCoroutine(InvincibleRoutine());
}
// 無敵狀態計時器與半透明效果
IEnumerator InvincibleRoutine()
{
isInvincible = true;
// 視覺呈現:讓小鳥變半透明,代表穿透/無敵狀態
if (spriteRenderer != null)
{
Color c = spriteRenderer.color;
c.a = 0.5f; // Alpha 設為 50%
spriteRenderer.color = c;
}
// 等待技能持續時間(預設 3 秒)
yield return new WaitForSeconds(skillDuration);
// 恢復正常狀態
isInvincible = false;
if (spriteRenderer != null)
{
Color c = spriteRenderer.color;
c.a = 1.0f; // 恢復完全不透明
spriteRenderer.color = c;
}
Debug.Log("技能時間結束,恢復實體碰撞。");
}
}
這次比較重要的是 isInvincible 和 InvincibleRoutine()。
當玩家使用技能後,isInvincible 會變成 true,碰到設定為 Rock 或 Ground 的物件時,就會跳過死亡判定。
另外也利用 SpriteRenderer 修改小鳥的透明度,讓玩家可以從畫面上看出目前正在使用技能。
技能目前設定持續 3 秒。
3 秒結束後,無敵狀態會關閉,小鳥也會從半透明恢復成原本的樣子。
而且使用技能的同時,羽毛數量會重新歸零,技能按鈕也會恢復成未解鎖的圖片。
因此玩家需要重新收集三根羽毛,才能再次使用技能。
目前這樣就形成了一個簡單的循環:
目前技能已經有基本效果,接下來應該會繼續測試實際遊玩的感覺。
除了目前的無敵穿透之外,原本也有想過讓技能發動時增加移動速度,因此之後可能會再加入加速效果。
另外,玉米道具目前也還沒有正式加入遊戲,之後會再思考它要和羽毛有什麼不同的功能。
今天主要是讓昨天完成的技能按鈕真正產生效果。
現在收集三根羽毛後,就可以使用技能。技能發動時,小鳥會變成半透明,並在3秒內無視岩石與地面的死亡碰撞。
技能結束後,小鳥會恢復正常,羽毛數量也會重新歸零。
這次算是把前幾天製作的幾個功能串得更完整,讓原本單純的「收集羽毛」開始真正成為遊戲玩法的一部分。