iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0
Build on Google AI

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

Day 13|製作技能效果(碰到障礙物跳過死亡判定)

  • 分享至 

  • xImage
  •  

讓收集到的羽毛有實際用途

昨天已經完成羽毛收集與技能按鈕的連動,收集三根羽毛後,技能按鈕會從灰色圖片替換成亮色圖片。
今天就繼續往下一步製作,讓這個技能真正有作用。
原本的構想是讓鳥在使用技能後可以暫時無視障礙物,所以這次先讓技能具備「無敵穿透」的效果。

目前希望技能可以做到:

  • 收集三根羽毛後解鎖技能。
  • 使用技能後,三根羽毛重新歸零。
  • 技能發動時,小鳥變成半透明。
  • 技能期間撞到岩石或地面不會死亡。
  • 經過一段時間後,恢復正常狀態。

加入技能效果

這次請 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 秒 → 重新收集羽毛

接下來的製作方向

目前技能已經有基本效果,接下來應該會繼續測試實際遊玩的感覺。
除了目前的無敵穿透之外,原本也有想過讓技能發動時增加移動速度,因此之後可能會再加入加速效果。
另外,玉米道具目前也還沒有正式加入遊戲,之後會再思考它要和羽毛有什麼不同的功能。

第十三天的成果

今天主要是讓昨天完成的技能按鈕真正產生效果。
現在收集三根羽毛後,就可以使用技能。技能發動時,小鳥會變成半透明,並在3秒內無視岩石與地面的死亡碰撞。
技能結束後,小鳥會恢復正常,羽毛數量也會重新歸零。
這次算是把前幾天製作的幾個功能串得更完整,讓原本單純的「收集羽毛」開始真正成為遊戲玩法的一部分。


上一篇
Day 12|讓收集羽毛與技能按鈕連動
下一篇
Day 14|技能新增加速效果
系列文
從基礎到實作:使用 Google AI 學習程式設計 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言