隨著熟練度,理解和實務應用上也會不同
在 Unity 遊戲開發中,可以使用 Action
和自定義 Delegate
來處理相同的事件或回調。下面將舉例說明如何使用這兩種方法來實現相同的功能,例如在角色進入觸發區域時觸發一個事件。
使用 Action
1. 定義 Action
並設置回調
首先,我們定義一個 Action
並設置回調方法:
using UnityEngine;
using System;
public class TriggerActionExample : MonoBehaviour
{
// 定義一個 Action
public Action OnPlayerEnter;
private void Start()
{
// 設置回調方法
OnPlayerEnter += PlayerEntered;
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
// 當玩家進入觸發區域時,調用 Action
OnPlayerEnter?.Invoke();
}
}
// 回調方法
private void PlayerEntered()
{
Debug.Log("Player has entered the trigger area.");
}
}
2. 使用 Action
將此腳本附加到有碰撞體(Collider)的遊戲物體上,並確保 Collider
被設置為 Is Trigger
。
使用自定義 Delegate
1. 定義委派和事件
首先,定義一個委派和一個事件,然後設置回調方法:
using UnityEngine;
public class TriggerDelegateExample : MonoBehaviour
{
// 定義一個委派
public delegate void PlayerEnterDelegate();
// 定義一個事件,使用委派作為類型
public event PlayerEnterDelegate OnPlayerEnter;
private void Start()
{
// 設置回調方法
OnPlayerEnter += PlayerEntered;
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
// 當玩家進入觸發區域時,觸發事件
OnPlayerEnter?.Invoke();
}
}
// 回調方法
private void PlayerEntered()
{
Debug.Log("Player has entered the trigger area.");
}
}
2. 使用自定義委派
將此腳本附加到有碰撞體(Collider)的遊戲物體上,並確保 Collider
被設置為 Is Trigger
。
總結
這兩個例子展示了如何在 Unity 中使用 Action
和自定義 Delegate
來實現相同的功能。在這兩種方法中,都使用了回調方法來處理玩家進入觸發區域的事件。Action
提供了一個更簡潔的方式來處理無返回值的回調,而自定義 Delegate
則提供了更多的靈活性,可以更好地描述特定的回調簽名。
在一些情況下,自定義委派(Delegate
)比 Action
更靈活,因為它允許您描述更特定的回調簽名。例如,當您需要處理多個參數或返回特定類型的結果時,自定義委派能夠提供更強的類型安全和清晰度。以下是一個具體的例子來說明這種靈活性。
情況:需要處理多個參數並返回結果
假設我們正在開發一個角色扮演遊戲,需要在玩家撿起物品時觸發一個事件。這個事件需要傳遞物品的名稱和數量,並且返回一個布爾值,指示物品是否成功撿起。
使用 Action
和 Func
在這種情況下,我們可以使用 Func
來處理多個參數並返回結果:
using UnityEngine;
using System;
public class PickupActionExample : MonoBehaviour
{
// 定義一個 Func,接受兩個參數並返回一個布爾值
public Func<string, int, bool> OnItemPickup;
private void Start()
{
// 設置回調方法
OnItemPickup += TryPickupItem;
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
// 當玩家進入觸發區域時,嘗試撿起物品
bool success = OnItemPickup?.Invoke("Health Potion", 1) ?? false;
if (success)
{
Debug.Log("Item successfully picked up.");
}
else
{
Debug.Log("Failed to pick up item.");
}
}
}
// 回調方法,嘗試撿起物品
private bool TryPickupItem(string itemName, int quantity)
{
// 實際的物品撿起邏輯,例如檢查背包空間等
Debug.Log($"Trying to pick up {quantity} of {itemName}.");
return true; // 假設物品總是能成功撿起
}
}
使用自定義委派
現在,我們使用自定義委派來處理相同的場景。這樣可以提供更多的語義清晰度:
using UnityEngine;
public class PickupDelegateExample : MonoBehaviour
{
// 定義一個委派,接受兩個參數並返回一個布爾值
public delegate bool ItemPickupDelegate(string itemName, int quantity);
// 定義一個事件,使用委派作為類型
public event ItemPickupDelegate OnItemPickup;
private void Start()
{
// 設置回調方法
OnItemPickup += TryPickupItem;
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
// 當玩家進入觸發區域時,嘗試撿起物品
bool success = OnItemPickup?.Invoke("Health Potion", 1) ?? false;
if (success)
{
Debug.Log("Item successfully picked up.");
}
else
{
Debug.Log("Failed to pick up item.");
}
}
}
// 回調方法,嘗試撿起物品
private bool TryPickupItem(string itemName, int quantity)
{
// 實際的物品撿起邏輯,例如檢查背包空間等
Debug.Log($"Trying to pick up {quantity} of {itemName}.");
return true; // 假設物品總是能成功撿起
}
}
總結
Action
和Func
:適用於大部分的情況,且代碼量較少。工作中遇到的案例完全使用Action來構建系統框架,我覺得是滿夠用的。Delegate
自定義委派:在需要描述更具體的回調簽名的情況下提供更多靈活性和清晰度。自定義委派可以明確地命名和描述參數及返回類型,號稱使代碼更具可讀性。由於Delegate
會使代碼量較多*2,為了減少代碼量,維持簡單易讀,使維護人員較為輕鬆,目前在 Unity專案中,比較少看到必需要用 Delegate的情況。
目前我負責維護的Unity遊戲,以使用Action居多。 下一篇將舉例 如何 使用 Action 實現跟 Func 相同的效果。