1. 程式人生 > >【UE4實用技能】寫一個異步回調的藍圖接口

【UE4實用技能】寫一個異步回調的藍圖接口

null clas ces 異步回調 generated 系統 ons rate prop

在做系統功能的時候經常需要到服務器去下載圖片然後再顯示,藍圖已經提供了這個接口供大家使用:
技術分享圖片

如果沒有別的其他需求,那這個接口就夠用了。

不過我們的項目需要在這個接口的基礎上加一些功能:
1.本地緩存(不需要每次都請求)
2.把圖片存放到硬盤(不需要每次重啟遊戲都重新下載)
3.設定一個文件數量閾值,超過這個值就刪掉最早的文件
4.判斷一下路徑,如果是本地的圖片直接加載,網絡圖片加載(整合所有圖片加載接口為唯一一個)

因為改動比較多所以不在DownloadImage這個接口上改,重新寫一個類來處理。(具體還是參考他的邏輯來寫)


首先先簡單講一下異步回調的藍圖接口改怎麽寫。
1.先繼承藍圖的異步回調基類

class CLIENT_API UImageDownloader : public UBlueprintAsyncActionBase

2.註冊一下回調接口

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGetImageDelegate, UTexture2D*, Texture);

    UPROPERTY(BlueprintAssignable)
        FGetImageDelegate OnSuccess;

    UPROPERTY(BlueprintAssignable)
        FGetImageDelegate OnFail;

這裏需要註意一下,回調FGetImageDelegate的聲明記得不要與其他類的名命重復了
3.補充一下構造函數


UImageDownloader::UImageDownloader(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    if (HasAnyFlags(RF_ClassDefaultObject) == false)
    {
        AddToRoot();
    }
}

4.提供唯一接口GetImage(FString URL)

    UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
    static UActImageDownloader* GetImage(FString URL);

大概就是這樣

#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Interfaces/IHttpRequest.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include <map>
#include "ImageDownloader.generated.h"

class UTexture2D;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGetImageDelegate, UTexture2D*, Texture);

UCLASS()
class CLIENT_API UImageDownloader : public UBlueprintAsyncActionBase
{
    //GENERATED_UCLASS_BODY()
    GENERATED_BODY()

public:
    UImageDownloader(const FObjectInitializer& ObjectInitializer);

    UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
    static UActImageDownloader* GetImage(FString URL);

    UPROPERTY(BlueprintAssignable)
        FGetImageDelegate OnSuccess;

    UPROPERTY(BlueprintAssignable)
        FGetImageDelegate OnFail;
};

具體邏輯如果有人看再寫吧,公司項目代碼不好復制,需要做專門做一個demo


稍微記錄一下幾個需要註意的點:

1.創建C++類的時候應該從ue編輯器那邊創建,這樣會少一點問題
技術分享圖片

2.構造函數最好自己寫, 不然經常編譯有問題。自己寫的話要用GENERATED_BODY()

UCLASS()
class CLIENT_API UActImageDownloader : public UBlueprintAsyncActionBase
{
    //GENERATED_UCLASS_BODY()
    GENERATED_BODY()

3.這一點很重要!我們寫異步回調的,藍圖的執行邏輯是先跑你的函數,再賦值兩個delegate。會導致的問題是,正常下載圖片沒有問題,如果加載本地圖片的話,實際是同步,這時候會找不到OnSuccess和OnFail的代理,也就是這兩個
技術分享圖片
這時候下面的流程就不走了。。。
解決方式就是,在代碼裏加一幀的延時。

    //如果直接調用Start的話,獲取網絡回調沒問題,但是獲取本地文件時會出現onsuccess綁的事件找不到的問題
    //調用DelayStart,加了個延時一幀調用
    FSimpleDelegateGraphTask::CreateAndDispatchWhenReady(
        FSimpleDelegateGraphTask::FDelegate::CreateLambda([=]() 
    {
        Start(URL);//這裏是你的邏輯
    }),
        TStatId(),
        nullptr,
        ENamedThreads::GameThread
        );

【UE4實用技能】寫一個異步回調的藍圖接口