0%

数字孪生

Async Http Request 模块

参考:【UE4 C++】HTTP 异步请求 json 数据和下载文件

Async Http Request 用于构建虚幻引擎与网络API之间的沟通,基于HttpRequest,向指定url的API发送信息

方法:

  1. 基于UBlueprintAsyncActionBase新建C++类

  2. 在build.cs中开启"HTTP" ,"Json","JsonUtilities"模块

    1
    2
    3
    PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" ,"UMG" ,"Niagara" , "NiagaraCore"});

    PrivateDependencyModuleNames.AddRange(new string[] { "HTTP" ,"Json","JsonUtilities"});

  3. 在新建C++类中构建BlueprintType结构体,用于存储数据

    1
    2
    3
    4
    5
    6
    USTRUCT(BlueprintType)
    struct F[结构体名称]
    {
    GENERATED_BODY()
    ...
    };

  4. 在类外建立动态单参数多播委托,以建立C++与蓝图之间的联系

    1
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(F[委托名],参数类,参数名);

  5. 在类内建立静态工厂函数,以暴露给蓝图使用

    1
    2
    UFUNCTION(BlueprintCallable,Category="AsyncHttp",meta=(BlueprintInternalUseOnly="true"))
    static UAsyncHttpRequest* AsyncHttpURLRequest(const FString& Url);

  6. 在类内建立委托节点,已发送信息

    1
    2
    3
    4
    5
    UPROPERTY(BlueprintAssignable)
    FPosRequestCompleteDelegate PosOnSucceeded;

    UPROPERTY(BlueprintAssignable)
    FPosRequestCompleteDelegate PosOnFailed;

  7. 在cpp中实现函数,发送请求,并编写接受信息实现

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// AsyncHttpRequest.h
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "Interfaces//IHttpRequest.h"
#include "AsyncHttpRequest.generated.h"

/**
* FPositionItem 用于承载获取的纬度与经度
*/
USTRUCT(BlueprintType)
struct FPositionItem
{
GENERATED_BODY()

FPositionItem(){}
FPositionItem(FString _Latitude,FString _Longitude):Latitude(_Latitude),Longitude(_Longitude){}

UPROPERTY(BlueprintReadOnly)
FString Latitude;

UPROPERTY(BlueprintReadOnly)
FString Longitude;
};

// 定义委托 以返回纬度与经度
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPosRequestCompleteDelegate,const FPositionItem&,Positon);

/**
*
*/
UCLASS()
class SCHOOL_API UAsyncHttpRequest : public UBlueprintAsyncActionBase
{
GENERATED_BODY()

public:
UAsyncHttpRequest();

UFUNCTION(BlueprintCallable,Category="AsyncHttp",meta=(BlueprintInternalUseOnly="true"))
static UAsyncHttpRequest* AsyncHttpURLRequest(const FString& Url);

void HttpRequestStar(const FString& Url);
void HttpRequest_PosRecHandle(FHttpRequestPtr Request,FHttpResponsePtr Response,bool bWasSuccess);

// 委托以输出结果
UPROPERTY(BlueprintAssignable)
FPosRequestCompleteDelegate PosOnSucceeded;

UPROPERTY(BlueprintAssignable)
FPosRequestCompleteDelegate PosOnFailed;

};

// AsyncHttpRequest.cpp
// Fill out your copyright notice in the Description page of Project Settings.


#include "AsyncHttpRequest.h"
#include "HttpModule.h"
#include "Interfaces/IHttpResponse.h"

UAsyncHttpRequest::UAsyncHttpRequest()
{
if(HasAnyFlags(RF_ClassDefaultObject) == false)
{
AddToRoot(); // 防止自动GC
}
}

// 静态工厂
UAsyncHttpRequest* UAsyncHttpRequest::AsyncHttpURLRequest(const FString& Url)
{
UAsyncHttpRequest* AsyncHttpRequest = NewObject<UAsyncHttpRequest>();
AsyncHttpRequest->HttpRequestStar(Url);
return AsyncHttpRequest;
}

// 开始请求
void UAsyncHttpRequest::HttpRequestStar(const FString& Url)
{
TSharedRef<IHttpRequest,ESPMode::ThreadSafe> Request = FHttpModule::Get().CreateRequest();
Request->SetVerb("GET");
Request->SetURL(Url);

Request->OnProcessRequestComplete().BindUObject(this,&UAsyncHttpRequest::HttpRequest_PosRecHandle); // 请求回调
Request->ProcessRequest();
}

// 回调函数
void UAsyncHttpRequest::HttpRequest_PosRecHandle(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccess)
{
if(bWasSuccess && Response.IsValid() && EHttpResponseCodes::IsOk(Response->GetResponseCode()))
{
TSharedPtr<FJsonObject> JsonObj;
TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(Response->GetContentAsString()); // 解析Json

// 反序列化
if(FJsonSerializer::Deserialize(JsonReader,JsonObj))
{
FString PosString;
if(JsonObj->TryGetStringField(TEXT("rectangle"),PosString))
{
FPositionItem GetPosItem;
bool IsReadSec = false;
for(const auto& c : PosString)
{
if(c == ',') IsReadSec = true;
else if(c == ';') break;
else if(IsReadSec) GetPosItem.Latitude += c;
else GetPosItem.Longitude += c;
}

// GEngine->AddOnScreenDebugMessage(-1,10.f,FColor::Cyan,PosString);
PosOnSucceeded.Broadcast(GetPosItem); // 成功执行并广播
RemoveFromRoot();
return ;
}
}
}

PosOnFailed.Broadcast({});
RemoveFromRoot(); // 手动GC
}