B站教学链接:https://space.bilibili.com/449549424?spm_id_from=333.1007.0.0
一、Http协议
Http协议网上有很多介绍,这里不过多介绍。需要可以参考
https://blog.csdn.net/lingxu6/article/details/124738027
二、前期准备
创建UE4 C++项目,在Build.cs中加入模块,UE4需要这些模块才能编译和加载Http和Json格式的数据
using UnrealBuildTool;
public class HttpProject : ModuleRules
{
public HttpProject(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay","Http","Json", "JsonUtilities","UMG" });
}
}
三、案例介绍
UE4封装了HttpModule,Json文件的序列化和反序列化,本案例就是使用了这些模块来进行web服务端的通信
服务器返回的数据是Json格式的数据
效果如下:
第一步:创建C++,三个UserWidget,名为StartWidget,RegisterWidget,LoginWidget,
第二步,创建一个GameMode ,名为StartGameMode
第三步 ,创建UMG,名为BP_MyStart,BP_Register,BP_Login
继承自C++的StartWidget,RegisterWidget,LoginWidget
第四步:代码写入StartWidget
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "MyUserWidget.h"
#include "Components/Button.h"
#include "StartWidget.generated.h"
/**
*
*/
UCLASS()
class HTTPPROJECT_API UStartWidget : public UMyUserWidget
{
GENERATED_BODY()
public:
UPROPERTY()
UButton* StartButton;
UPROPERTY()
UButton* RegisterButton;
UPROPERTY()
UButton* QuitButton;
public:
virtual bool Initialize() override;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "StartWidget.h"
bool UStartWidget::Initialize()
{
if (!Super::Initialize())
{
return false;
}
//初始化开始按钮
StartButton = Cast<UButton>(GetWidgetFromName(TEXT("Button_Start")));
//初始化注册按钮
RegisterButton = Cast<UButton>(GetWidgetFromName(TEXT("Button_Register")));
//初始化退出按钮
QuitButton = Cast<UButton>(GetWidgetFromName(TEXT("Button_Quit")));
return true;
}
RegisterWidget代码
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "MyUserWidget.h"
#include "Components/Button.h"
#include "Components/EditableTextBox.h"
#include "Components/TextBlock.h"
#include "HTTP/Public/Interfaces/IHttpRequest.h"
#include "HTTP/Public/Interfaces/IHttpResponse.h"
#include "HTTP/Public/Interfaces/IHttpBase.h"
#include "HTTP/Public/HttpModule.h"
#include "Json/Public/Serialization/JsonWriter.h"
#include "Json/Public/Serialization/JsonReader.h"
#include "Json/Public/Serialization/JsonSerializer.h"
#include "Json/Public/Policies/CondensedJsonPrintPolicy.h"
#include "Json/Public/Dom/JsonObject.h"
#include "RegisterWidget.generated.h"
/**
*
*/
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnRegisterResultDelegate, bool, result, FString, message);
UCLASS()
class HTTPPROJECT_API URegisterWidget : public UMyUserWidget
{
GENERATED_BODY()
public:
UPROPERTY()
UButton* RegisterBtn;
UPROPERTY()
UButton* BackBtn;
UPROPERTY()
UEditableTextBox* NicknameInput;
UPROPERTY()
UEditableTextBox* PasswordInput;
UPROPERTY()
UEditableTextBox* RePasswordInput;
UPROPERTY(BlueprintAssignable, Category = "Register")
FOnRegisterResultDelegate OnRegisterResultDelegate;
public:
virtual bool Initialize() override;
UFUNCTION()
void RegisterButtonOnClickEvent();
//注册函数
void AccountRegisterFromServer(FString nickname,FString password);
private:
//绑定回调函数
void RequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bIsSuccess);
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "RegisterWidget.h"
bool URegisterWidget::Initialize()
{
if (!Super::Initialize())
{
return false;
}
//初始化返回按钮
BackBtn = Cast<UButton>(GetWidgetFromName(TEXT("Button_Return")));
//初始化注册按钮
RegisterBtn = Cast<UButton>(GetWidgetFromName(TEXT("Button_Register")));
//初始化账号输入框
NicknameInput = Cast<UEditableTextBox>(GetWidgetFromName(TEXT("EditableText_Nickname")));
//初始化密码输入框
PasswordInput = Cast<UEditableTextBox>(GetWidgetFromName(TEXT("EditableText_Password")));
//初始化重复密码输入框
RePasswordInput = Cast<UEditableTextBox>(GetWidgetFromName(TEXT("EditableText_RePassword")));
//初始化绑定注册函数
RegisterBtn->OnClicked.AddDynamic(this, &URegisterWidget::RegisterButtonOnClickEvent);
return true;
}
void URegisterWidget::RegisterButtonOnClickEvent()
{
FString Account = NicknameInput->GetText().ToString();
FString PassWord1 = PasswordInput->GetText().ToString();
FString RePassWord1 = RePasswordInput->GetText().ToString();
if (Account.Len()< 2 || Account.Len() > 6)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("NickName is too long"));
return;
}
if (!PassWord1.Equals(RePassWord1))
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Second password is error"));
}
AccountRegisterFromServer(Account,PassWord1);
RegisterBtn->SetIsEnabled(false);
}
void URegisterWidget::AccountRegisterFromServer(FString nickname, FString password)
{
FString Serverdata;
TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter = TJsonWriterFactory<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>::Create(&Serverdata);
JsonWriter->WriteObjectStart();
//写入账号
JsonWriter->WriteValue("nickname", nickname);
//写入密码
JsonWriter->WriteValue("password", password);
//关闭写入
JsonWriter->WriteObjectEnd();
//关闭json写入器
JsonWriter->Close();
//创建Http 请求
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> HttpRequest = FHttpModule::Get().CreateRequest();
//设置Header
HttpRequest->SetHeader("Content-Type", "application/json;charset=UTF-8");
HttpRequest->SetVerb("POST");
//设置请求地址
HttpRequest->SetURL("https://........................................");
//设置请求发送的数据
HttpRequest->SetContentAsString(Serverdata);
//绑定回调
HttpRequest->OnProcessRequestComplete().BindUObject(this, &URegisterWidget::RequestComplete);
//发送请求
HttpRequest->ProcessRequest();
}
void URegisterWidget::RequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bIsSuccess)
{
UE_LOG(LogTemp, Warning, TEXT(">>request complete"));
UE_LOG(LogTemp, Warning, TEXT("%s"), *(ResponsePtr->GetContentAsString()));
if (!EHttpResponseCodes::IsOk(ResponsePtr->GetResponseCode()))
{
OnRegisterResultDelegate.Broadcast(false, TEXT("Invalid Network"));
UE_LOG(LogTemp, Warning, TEXT("Invalid Network"));
return;
}
//创建一个Json解析器
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(ResponsePtr->GetContentAsString());
//创建一个Json对象
TSharedPtr<FJsonObject> JsonObject;
//Json反序列化
bool bIsOk = FJsonSerializer::Deserialize(JsonReader, JsonObject);
//判断解析是否成功
if (bIsOk)
{
int code = JsonObject->GetIntegerField("code");
FString msg = JsonObject->GetStringField("msg");
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Msg is : %s"),*msg));
if (code != 0)
{
OnRegisterResultDelegate.Broadcast(false, *msg);
return;
}
TSharedPtr<FJsonObject> DataObject = JsonObject->GetObjectField("data");
OnRegisterResultDelegate.Broadcast(true, TEXT("Success"));
UE_LOG(LogTemp, Warning, TEXT("Success"));
}
}
LoginWidget代码
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "LoginActor.generated.h"
UCLASS()
class HTTPPROJECT_API ALoginActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ALoginActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "MyUserWidget.h"
#include "Components/Button.h"
#include "Components/EditableTextBox.h"
#include "Components/TextBlock.h"
#include "HTTP/Public/Interfaces/IHttpRequest.h"
#include "HTTP/Public/Interfaces/IHttpResponse.h"
#include "HTTP/Public/Interfaces/IHttpBase.h"
#include "HTTP/Public/HttpModule.h"
#include "Json/Public/Serialization/JsonWriter.h"
#include "Json/Public/Serialization/JsonReader.h"
#include "Json/Public/Serialization/JsonSerializer.h"
#include "Json/Public/Policies/CondensedJsonPrintPolicy.h"
#include "Json/Public/Dom/JsonObject.h"
#include "LoginWidget.generated.h"
/**
*
*/
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnLoginResultDelegate, bool, result, FString, message);
UCLASS()
class HTTPPROJECT_API ULoginWidget : public UMyUserWidget
{
GENERATED_BODY()
public:
UPROPERTY()
UButton* LoginBtn;
UPROPERTY()
UButton* ReturnBtn;
UPROPERTY()
UEditableTextBox* NicknameInput;
UPROPERTY()
UEditableTextBox* PasswordInput;
public:
virtual bool Initialize() override;
UPROPERTY(BlueprintAssignable, Category = "Register")
FOnLoginResultDelegate OnLoginResultDelegate;
//点击登陆函数
UFUNCTION()
void LoginButtonOnClickEvent();
//登陆方法函数
void AccountLoginFromServer(FString Nickname,FString Password);
private:
//绑定回调函数
void RequestComplete(FHttpRequestPtr RequestPtr, FHttpResponsePtr ResponsePtr, bool bIsSuccess);
};
StartGameMode的代码
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameMode.h"
#include "StartWidget.h"
#include "RegisterWidget.h"
#include "LoginWidget.h"
#include "StartGameMode.generated.h"
/**
*
*/
UCLASS()
class HTTPPROJECT_API AStartGameMode : public AGameMode
{
GENERATED_BODY()
public:
UPROPERTY()
UStartWidget* MyStartWidget;
UPROPERTY()
URegisterWidget* MyRegisterWidget;
UPROPERTY()
ULoginWidget* MyLoginWidget;
public:
virtual void BeginPlay() override;
UFUNCTION()
void RegisterBtnOnClickEvent();
UFUNCTION()
void RegisterBackBtnOnClickEvent();
UFUNCTION()
void StartBtnOnClickEvent();
UFUNCTION()
void LoginBackBtnOnClickEvent();
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "StartGameMode.h"
void AStartGameMode::BeginPlay()
{
Super::BeginPlay();
MyStartWidget = CreateWidget<UStartWidget>(GetWorld(),LoadClass<UStartWidget>(nullptr,TEXT("WidgetBlueprint'/Game/BP_Start.BP_Start_C'")));
if (MyStartWidget)
{
MyStartWidget->AddToViewport();
MyStartWidget->RegisterButton->OnClicked.AddDynamic(this, &AStartGameMode::RegisterBtnOnClickEvent);
MyStartWidget->StartButton->OnClicked.AddDynamic(this,&AStartGameMode::StartBtnOnClickEvent);
}
MyRegisterWidget = CreateWidget<URegisterWidget>(GetWorld(), LoadClass<URegisterWidget>(nullptr, TEXT("WidgetBlueprint'/Game/BP_Register.BP_Register_C'")));
if (MyRegisterWidget)
{
MyRegisterWidget->BackBtn->OnClicked.AddDynamic(this, &AStartGameMode::RegisterBackBtnOnClickEvent);
}
MyLoginWidget = CreateWidget<ULoginWidget>(GetWorld(), LoadClass<ULoginWidget>(nullptr,TEXT("WidgetBlueprint'/Game/BP_Login.BP_Login_C'")));
if (MyLoginWidget)
{
MyLoginWidget->ReturnBtn->OnClicked.AddDynamic(this, &AStartGameMode::LoginBackBtnOnClickEvent);
}
}
void AStartGameMode::RegisterBtnOnClickEvent()
{
MyStartWidget->RemoveFromParent();
MyRegisterWidget->AddToViewport();
}
void AStartGameMode::RegisterBackBtnOnClickEvent()
{
MyRegisterWidget->RemoveFromParent();
MyStartWidget->AddToViewport();
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("RegisterBack"));
}
void AStartGameMode::StartBtnOnClickEvent()
{
MyStartWidget->RemoveFromParent();
MyLoginWidget->AddToViewport();
}
void AStartGameMode::LoginBackBtnOnClickEvent()
{
MyLoginWidget->RemoveFromParent();
MyStartWidget->AddToViewport();
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("LoginBack"));
}
第五步:世界设置中选中StartGameMode
第六步:测试运行
到此即可