很多時候我們是通過代碼寫遊戲邏輯,當邏輯執行到某個狀態時,能夠通過事件的方式觸發另外一段邏輯,而觸發的這段邏輯希望在藍圖中實現,這時候就存在一個代碼和藍圖事件連接和調用的問題。實現此功能很簡單,有兩種方式,一種是通過代碼定義事件接口,實現邏輯完全放在藍圖中,代碼中沒有默認實現邏輯;另外一種是在代碼中有默認實現邏輯,但在藍圖中可以重寫。
針對第一種方式,可以直接參考最常用的Actor類中的BeginPlay事件邏輯的實現方式,現在把相應的部分代碼顯示如下:
/** Event when play begins for this actor. */
UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "BeginPlay"))
void ReceiveBeginPlay();
/** Event when play begins for this actor. */
virtual void BeginPlay();
上面的ReceiveBeginPlay就是要在藍圖中實現的事件邏輯,該函數在代碼中沒有函數體,這裏很關鍵的就是BlueprintImplementableEvent函數屬性,它定義了該函數需要在藍圖中實現,並且是事件形式。
事件本身其實也是函數調用,那這個事件是怎麼觸發的呢?也就是ReceiveBeginPlay函數怎麼被調用呢?相比你也猜到了,看下BeginPlay函數的實現就明白了,ReceiveBeginPlay是在BeginPlay函數中調用的,
void AActor::BeginPlay()
{
......
ReceiveBeginPlay();
......
}
這下就真相大白了,實現方式可以總結一下就是:代碼中聲明事件函數但沒有函數體,將函數屬性設置爲BlueprintImplementableEvent,在代碼中相應地方調用該函數,我們暫且叫藍圖事件函數,或者直接稱作在代碼中觸發事件吧。
上面的這種方式就是必須在藍圖中實現事件觸發後的邏輯,否則不起任何作用,另外一種則是可以在代碼中實現默認的邏輯,可以在藍圖中重寫。
這種方式我們可以參考官方文檔中的一個示例,這裏我們摘錄核心代碼,
UFUNCTION(BlueprintNativeEvent)
void CountdownHasFinished();
virtual void CountdownHasFinished_Implementation();
事件函數的調用和第一種方式一樣,直接在相應代碼邏輯處調用即可,但要注意,調用的是事件函數聲明時的函數名,不是實現函數名,即上面的CountdownHasFinished而不是CountdownHasFinished_Implementation。
以上兩種方式在遊戲開發中經常會使用,比如在做多人遊戲時,當客戶端與服務器的網絡斷開時,我們可能要通知玩家網絡已斷開連接,這時我們可以在響應服務器的連接處理的邏輯處調用一個藍圖事件函數,我們在藍圖中處理具體的網絡連接斷開提示等邏輯。
Unreal技術交流學習請加羣:173090312 Unreal高級開發羣