开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2230

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 1709|回复: 14

[留人醉] UE4实现登录注册功能

[复制链接]  [移动端链接]
排名
26573
昨日变化
3

1

主题

23

帖子

122

积分

Rank: 9Rank: 9Rank: 9

UID
168263
好友
0
蛮牛币
99
威望
0
注册时间
2016-9-12
在线时间
80 小时
最后登录
2018-6-11
发表于 2018-1-2 15:10:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本节主要讲解游戏的起始页,登录页,注册页的实现。主要讲解的知识点是C++如何使用UMG做界面开发和UE4如何实现HTTP通讯及JSON的序列化和反序列化。视频教程链接可到蛮牛教育观看,详情链接点击:无尽之刃·文明
1、起始页开发
1、创建蓝图版UserWidget
首先创建好UI目录,把UI素材导入到目录中。

创建起始页蓝图版的UserWidget,按照上述成品图设计即可。包含的元素如下:
  • 背景图片
  • Logo图片
  • 开始游戏按钮
  • 注册账号按钮
  • 退出游戏按钮
  • 版本信息文本
注意事项:设计UMG界面时特别需要注意锚点的使用以及布局面板的使用,起始页面使用的是
VerticalPanel对右面的Logo到版本信息进行了垂直布局。
2、创建C++版UserWidget
首先我们要在Build.cs里面把UMG和Slate配置上去。
创建蓝图UserWidget的父类,让上面的蓝图继承之。因为我们要获取起始页面具体的按钮的引用来进一步对UMG的Widget进行操作。
根据上面的界面设计,我们在头文件中创建了三个UButton,分别表示开始游戏、注册游戏、退出游戏。我们希望这三个成员变量在子类蓝图UMG创建时自动初始化,因此我们重写UserWidget的Initialize()方法,在蓝图UMG初始化时自动初始化父类(UStartUserWidget)的三个按钮成员变量即可。
退出游戏按钮的事件非常的简单,因此我们这里在父类实现即可。添加OnClicked事件并实现退出游戏的逻辑。
综上,我们可以看出UMG的基本的开发思路,首先要设计好要展示的蓝图版的UMG,然后创建C++版的UserWidget,其成员变量/方法应是关于蓝图版的UMG的数据,以方便来使用蓝图版的UMG里面定义的控件。然后回到蓝图版的UMG让其父类继承之。
起始页头文件(StartUserWidget.h)
/**
* 游戏开始界面
*/
UCLASS()
class INFINITYBLADE_API UStartUserWidget : public UUserWidget
{
        GENERATED_BODY()
        
public:
        /** 开始游戏按钮 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UButton* StartBtn;
        /** 注册游戏按钮 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UButton* RegisterBtn;
        /** 退出游戏按钮 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UButton* ExitBtn;
public:
        /** 创建UserWidget对象后执行的生命周期方法 */
        virtual bool Initialize() override;
        /** 初始化控件引用 */
        void Init();
        /** 退出游戏按钮点击事件 */
        UFUNCTION()
        void ExitBtnClickedEvent();
};
起始页cpp文件(StartUserWidget.cpp)
#include "StartUserWidget.h"

/** 创建UserWidget对象后执行的生命周期方法 */
bool UStartUserWidget::Initialize()
{
        if (!Super::Initialize())
        {
                return false;
        }

        /** 初始化控件的引用 */
        Init();

        return true;
}

/** 初始化控件引用 */
void UStartUserWidget::Init()
{
        /** 初始化游戏开始按钮 */
        StartBtn = Cast<UButton>(GetWidgetFromName(TEXT("Button_Start")));
        /** 初始化游戏注册按钮 */
        RegisterBtn = Cast<UButton>(GetWidgetFromName(TEXT("Button_Register")));
        /** 初始化游戏退出按钮 */
        ExitBtn = Cast<UButton>(GetWidgetFromName(TEXT("Button_Exit")));
        /** 设置退出游戏按钮的点击事件 */
        ExitBtn->OnClicked.AddDynamic(this, &UStartUserWidget::ExitBtnClickedEvent);
}

/** 退出游戏按钮点击事件 */
void UStartUserWidget::ExitBtnClickedEvent()
{
        /** 退出游戏 */
        UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit);
}
3、事件的监听
上面我们已经把退出游戏按钮的点击事件实现了,还有开始游戏注册账号两个按钮的事件没有实现,此时,我们考虑一下MVC的设计模式以及高内聚低耦合的模式,我们应该把那两个按钮的事件放在哪里呢?
首先肯定是不能放到自己写的C++父类里面的,如果放在里面的话,我们首先要获取开始游戏页面和注册游戏页面的控件引用,这样就不符合低耦合的概念了。所以这里考虑UE4提供的Gameplay框架,我们首先是考虑放到了GameMode这个类里面。下面是游戏首页关卡的游戏模式类,该类里面拥有我们对于UI的处理逻辑。我们看到还有两个成员变量分别是登录页面和注册页面的UI,我们现在先暂时不考虑,下面会讲解这两个页面的开发。
我们首先看一下起始页面UI的初始化、开始游戏按钮的回调事件和注册游戏按钮的回调事件。
  • 初始化UStartUserWidget对象这里采用的静态加载LoadClass()方法,我们也可以创建游戏模式的蓝图,使用TSubclassOf的方式来加载,这里技术细节不具体赘述了。初始化完成后把该UMG添加到Viewport即可。
  • 开始游戏按钮和注册游戏按钮只需要添加OnClicked事件即可。在这两个游戏按钮的点击事件上,我们动态的切换Viewport展示的UMG即可。
至此,我们已经把游戏起始页的基本功能完成了,这里只是粗略的赘述了一下,如果想更了解细节可以看源代码来自己手动实现。
首页游戏关卡的游戏模式类的头文件:EmptyGameMode.h
/**
* 初始化关卡游戏模式
*/
UCLASS()
class INFINITYBLADE_API AEmptyGameMode : public AGameMode
{
        GENERATED_BODY()
public:
        /** 起始页面UI */
        UPROPERTY()
        UStartUserWidget* StartUI;
        /** 登录页面UI */
        UPROPERTY()
        ULoginUserWidget* LoginUI;
        /** 注册页面UI */
        UPROPERTY()
        URegisterUserWidget* RegisterUI;
public:
        /** 游戏开始调用的方法 */
        virtual void BeginPlay() override;
        /** 开始游戏按钮回调事件 */
        UFUNCTION()
        void StartBtnClickedEvent();
        /** 注册按钮回调事件 */
        UFUNCTION()
        void RegisterBtnClickedEvent();
        /** 登录页返回按钮回调事件 */
        UFUNCTION()
        void LoginBackBtnClickedEvent();
        /** 注册页返回按钮回调事件 */
        UFUNCTION()
        void RegisterBackBtnClickedEvent();
};
```​​​​

首页游戏关卡的游戏模式类cpp文件:EmptyGameMode.cpp

``` C++
#include "EmptyGameMode.h"

/** 游戏开始调用的方法 */
void AEmptyGameMode::BeginPlay()
{
        /** 初始化起始页UI */
        StartUI = CreateWidget<UStartUserWidget>(GetGameInstance(), LoadClass<UStartUserWidget>(nullptr, TEXT("WidgetBlueprint'/Game/UI/Start/UI_Start.UI_Start_C'")));
        /** 设置开始游戏按钮的点击事件 */
        StartUI->StartBtn->OnClicked.AddDynamic(this, &AEmptyGameMode::StartBtnClickedEvent);
        /** 设置注册按钮的点击事件 */
        StartUI->RegisterBtn->OnClicked.AddDynamic(this, &AEmptyGameMode::RegisterBtnClickedEvent);
        
        /**初始化登录页UI */
        LoginUI = CreateWidget<ULoginUserWidget>(GetGameInstance(), LoadClass<ULoginUserWidget>(nullptr, TEXT("WidgetBlueprint'/Game/UI/Login/UI_Login.UI_Login_C'")));
        /** 设置返回按钮的点击事件 */
        LoginUI->BackBtn->OnClicked.AddDynamic(this, &AEmptyGameMode::LoginBackBtnClickedEvent);

        /**初始化注册页UI */
        RegisterUI = CreateWidget<URegisterUserWidget>(GetGameInstance(), LoadClass<URegisterUserWidget>(nullptr, TEXT("WidgetBlueprint'/Game/UI/Register/UI_Register.UI_Register_C'")));
        /** 设置返回按钮的点击事件 */
        RegisterUI->BackBtn->OnClicked.AddDynamic(this, &AEmptyGameMode::RegisterBackBtnClickedEvent);

        /** 添加起始页到视口 */
        StartUI->AddToViewport();
        
}

/** 开始游戏按钮回调事件 */
void AEmptyGameMode::StartBtnClickedEvent()
{
        /** 移除起始页UI */
        StartUI->RemoveFromViewport();
        /** 添加登录页UI到视口 */
        LoginUI->AddToViewport();
}

/** 注册按钮回调事件 */
void AEmptyGameMode::RegisterBtnClickedEvent()
{
        /** 移除起始页UI */
        StartUI->RemoveFromViewport();
        /** 添加注册页UI到视口 */
        RegisterUI->AddToViewport();
}

/** 登录页返回按钮回调事件 */
void AEmptyGameMode::LoginBackBtnClickedEvent()
{
        /** 移除登录页UI */
        LoginUI->RemoveFromViewport();
        /** 添加起始页UI到视口 */
        StartUI->AddToViewport();
}

/** 注册页返回按钮回调事件 */
void AEmptyGameMode::RegisterBackBtnClickedEvent()
{
        /** 移除登录页UI */
        RegisterUI->RemoveFromViewport();
        /** 添加起始页UI到视口 */
        StartUI->AddToViewport();
}
2、注册页开发
1、蓝图的创建及C++的创建
首先我们看一下注册页面的布局,典型的上下结构,因此我们首先根据素材导入UE4后创建蓝图版的UMG,然后进行设计。需要注意的是要学会使用布局面板和锚点来设计,保证页面在伸缩时保持弹性。接着我们看一下非样式的控件有哪些:
  • 左上角的返回按钮
  • 账号输入框
  • 密码输入框
  • 确认密码输入框
  • 注册按钮
  • 加载控件,一个选装的Loading框
  • Toast控件,显示错误信息的自定义面板,后面会介绍
根据上面的描述,我们为该UMG创建父类。注册页面我们要是使用JSON来向服务器发送数据。同时使用HTTP与服务器进行交互,所以,我们要在Build.cs里面配置JSON和HTTP。
Web服务器已经对非进行了数据校验,但是数据加密并没有实现,这里应该对账号和密码进行MD5加密,这里没有实现,但是企业级项目大家要注意。我们在本地端就简单的实现两次密码是否保持一致的校验即可。如果密码错误,我们就显示Toast面板来提示。注意:这里有个问题,提示信息如果是中文在安卓打包时会报错,现在还没去解决,因此使用的英文。
本地端进行简单的数据校验以后,就进行服务器的请求,首先我们会先对输入的用户名和密码进行拼接,形成JSON数据串,然后再提交到服务器上。具体的代码在cpp文件里可以看到,注释也比较详细。这里提交服务器的时候,比较友好的是先把注册按钮禁用掉,然后显示Loading框,当服务器返回结果后再把Loading框去掉,把注册按钮的禁用去掉。
注册页面头文件:RegisterUserWidget.h
/**
* 注册界面UI
*/
UCLASS()
class INFINITYBLADE_API URegisterUserWidget : public UUserWidget
{
        GENERATED_BODY()
        
public:
        /** 账号输入框 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UEditableTextBox* AccountBox;
        /** 密码输入框 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UEditableTextBox* PasswordBox;
        /** 密码确认输入框 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UEditableTextBox* RePasswordBox;
        /** 注册按钮 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UButton* RegisterBtn;
        /** 后退按钮 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UButton* BackBtn;
        /** 加载控件 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UCircularThrobber* LoadingCircle;
        /** Toast控件 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UToastUserWidget* ToastWidget;
public:
        /** 对象创建后调用的方法 */
        virtual bool Initialize() override;
public:
        /** 初始化控件引用 */
        void Init();
public:
        /** 注册按钮点击事件 */
        UFUNCTION()
        void RegisterBtnClickedEvent();
        /** 注册方法 */
        void RegisterServer(FString& Nickname,FString& Password);
        /** 注册方法的服务器回调 */
        void ServerRegisterCompleteCallback(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bIsSuccessful);
};
注册页面cpp文件:RegisterUserWidget.cpp
/** 对象创建后调用的方法 */
bool URegisterUserWidget::Initialize()
{
        if (!Super::Initialize())
        {
                return false;
        }

        /** 初始化控件引用 */
        Init();

        return true;
}

/** 初始化控件引用 */
void URegisterUserWidget::Init()
{
        /** 初始化账号输入框 */
        AccountBox = Cast<UEditableTextBox>(GetWidgetFromName(TEXT("EditableTextBox_Account")));
        /** 初始化密码输入框 */
        PasswordBox = Cast<UEditableTextBox>(GetWidgetFromName(TEXT("EditableTextBox_Password")));
        /** 初始化确认密码输入框 */
        RePasswordBox = Cast<UEditableTextBox>(GetWidgetFromName(TEXT("EditableTextBox_RePassword")));
        /** 初始化注册按钮 */
        RegisterBtn = Cast<UButton>(GetWidgetFromName(TEXT("Button_Register")));
        /** 设置注册按钮的点击事件 */
        RegisterBtn->OnClicked.AddDynamic(this, &URegisterUserWidget::RegisterBtnClickedEvent);
        /** 初始化后退按钮 */
        BackBtn = Cast<UButton>(GetWidgetFromName(TEXT("Button_Back")));
        /** 初始化加载控件 */
        LoadingCircle = Cast<UCircularThrobber>(GetWidgetFromName(TEXT("CircularThrobber")));
        /** 初始化Toast控件 */
        ToastWidget = Cast<UToastUserWidget>(GetWidgetFromName(TEXT("UI_Toast")));
}

/** 注册按钮点击事件 */
void URegisterUserWidget::RegisterBtnClickedEvent()
{
        /** 获取注册用户名 */
        FString Nickname = AccountBox->GetText().ToString();
        /** 获取注册密码 */
        FString Password = PasswordBox->GetText().ToString();
        /** 获取确认的注册密码 */
        FString RePassword = RePasswordBox->GetText().ToString();
        /** 判断两次输入的密码是否一致 */
        if (!Password.Equals(RePassword))
        {
                /** 设置提示信息 */
                ToastWidget->Msg->SetText(FText::FromString("The Two Input Password Is Not Same!"));
                /** 显示Toast */
                ToastWidget->SetVisibility(ESlateVisibility::Visible);
                return;
        }
        /** 注册服务器 */
        RegisterServer(Nickname, Password);
}

/** 注册方法 */
void URegisterUserWidget::RegisterServer(FString& Nickname, FString& Password)
{
        /** 创建要提交的数据 */
        FString Data;

        /** 创建Json写入器 */
        TSharedPtr<TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>> JsonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&Data);
        /** 开始写入Json对象 */
        JsonWriter->WriteObjectStart();
        /** 写入昵称 */
        JsonWriter->WriteValue("nickname", Nickname);
        /** 写入密码 */
        JsonWriter->WriteValue("password", Password);
        /** 结束写入Json对象 */
        JsonWriter->WriteObjectEnd();
        /** 关闭Json写入器 */
        JsonWriter->Close();

        /** 创建Http请求 */
        TSharedPtr<IHttpRequest> Request = FHttpModule::Get().CreateRequest();
        /** 设置请求头 */
        Request->SetHeader("Content-Type", "application/json;charset=utf-8");
        /** 设置请求方式 */
        Request->SetVerb("POST");
        /** 设置请求的URL */
        Request->SetURL("http://www.ujeat.com:7900/user/register-user");
        /** 设置上传的数据 */
        Request->SetContentAsString(Data);
        /** 设置请求成功后的回调事件 */
        Request->OnProcessRequestComplete().BindUObject(this, &URegisterUserWidget::ServerRegisterCompleteCallback);
        /** 处理请求 */
        Request->ProcessRequest();

        /** 显示进度控件 */
        LoadingCircle->SetVisibility(ESlateVisibility::Visible);
        /** 设置注册按钮不可用 */
        RegisterBtn->SetIsEnabled(false);
}
/** 注册方法的服务器回调 */
void URegisterUserWidget::ServerRegisterCompleteCallback(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bIsSuccessful)
{
        /** 隐藏进度控件 */
        LoadingCircle->SetVisibility(ESlateVisibility::Hidden);
        /** 设置注册按钮可用 */
        RegisterBtn->SetIsEnabled(true);

        /** 判断服务器返回状态 */
        if (!EHttpResponseCodes::IsOk(Response->GetResponseCode()))
        {
                /** 如果服务器未返回成功则返回 */
                return;
        }

        /** 创建服务器返回的内容 */
        FString Result = Response->GetContentAsString();
        /** 创建要解析的JSON对象 */
        TSharedPtr<FJsonObject> JsonObject;
        /** 创建Json解析器 */
        TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(Result);
        /** 解析Json */
        bool bIsParseSuccess = FJsonSerializer::Deserialize(JsonReader, JsonObject);
        /** 判断是否解析成功 */
        if (bIsParseSuccess)
        {
                /** 获取响应状态 */
                FString ResponseStatus = JsonObject->GetStringField("status");
                /** 获取响应信息 */
                FString ResponseMsg = JsonObject->GetStringField("msg");
               
                /** 设置服务器响应信息 */
                ToastWidget->Msg->SetText(FText::FromString(ResponseMsg));
                /** 显示Toast */
                ToastWidget->SetVisibility(ESlateVisibility::Visible);
               
        }
}
2、Toast面板
这里对Toast面板进行简单的介绍,其实和上面开发UMG的思路一致,创建蓝图版再创建C++版,然后C++里持有引用,这里可以看到,引用的控件只是简单的Text控件,我们只对其SetText()即可,这里使用了BackgroundBlur控件进行了背景的模糊处理,这里就不过多赘述了,大家可以自己实现一下。
3、登录页开发
登录页面和注册页面类似,这里只把代码复制上,大家可以自行Review,实现思路和注册页面类似,甚至更简单。登录成功以后我们切换关卡到主战场的Level,这里因为后期有排行榜,所以用户登录成功以后的信息需要进行保存,这里我存到了GameInstace里面,顾名思义就是游戏实例,其生命周期是伴随游戏开始到游戏退出的,如果想做持久化的话,这里可以选用其它的方式如SQLite,这里以后再去研究,我们先假定每次打开游戏都需要进行登录。
登录页面头文件:LoginUserWidget.h
/**
* 登录界面UI
*/
UCLASS()
class INFINITYBLADE_API ULoginUserWidget : public UUserWidget
{
        GENERATED_BODY()

public:
        /** 账号输入框 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UEditableTextBox* AccountBox;
        /** 密码输入框 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UEditableTextBox* PasswordBox;
        /** 登录按钮 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UButton* LoginBtn;
        /** 后退按钮 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UButton* BackBtn;
        /** 加载控件 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UCircularThrobber* LoadingCircle;
        /** Toast控件 */
        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "UI")
        UToastUserWidget* ToastWidget;
public:
        /** 创建UserWidget对象后触发 */
        virtual bool Initialize() override;
public:
        /** 初始化控件引用 */
        void Init();
public:
        /** 登录按钮点击事件 */
        UFUNCTION()
        void LoginBtnClickedEvent();
        /** 用户登录 */
        void LoginServer(FString& Nickname,FString& Password);
        /** 服务器响应的回调事件 */
        void ServerCompleteCallback(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bIsSuccessful);
};
登录页面cpp文件:LoginUserWidget.cpp
#include "LoginUserWidget.h"

/** 创建UserWidget对象后触发 */
bool ULoginUserWidget::Initialize()
{
        /** 不加这个判断可能会报错 */
        if (!Super::Initialize())
        {
                return false;
        }

        /** 初始化对象的引用 */
        Init();

        return true;
}

/** 初始化控件引用 */
void ULoginUserWidget::Init()
{
        /** 初始化账号输入框 */
        AccountBox = Cast<UEditableTextBox>(GetWidgetFromName(TEXT("EditableTextBox_Account")));
        /** 初始化密码输入框 */
        PasswordBox = Cast<UEditableTextBox>(GetWidgetFromName(TEXT("EditableTextBox_Password")));
        /** 初始化登录按钮 */
        LoginBtn = Cast<UButton>(GetWidgetFromName(TEXT("Button_Login")));
        /** 设置登录按钮的点击事件 */
        LoginBtn->OnClicked.AddDynamic(this, &ULoginUserWidget::LoginBtnClickedEvent);
        /** 初始化后退按钮 */
        BackBtn = Cast<UButton>(GetWidgetFromName(TEXT("Button_Back")));
        /** 初始化加载控件 */
        LoadingCircle = Cast<UCircularThrobber>(GetWidgetFromName(TEXT("CircularThrobber")));
        /** 初始化Toast控件 */
        ToastWidget = Cast<UToastUserWidget>(GetWidgetFromName(TEXT("UI_Toast")));
}

/** 登录按钮点击事件 */
void ULoginUserWidget::LoginBtnClickedEvent()
{
        /** 获取输入的用户名 */
        FString Nickname = AccountBox->GetText().ToString();
        /** 获取输入的密码 */
        FString Password = PasswordBox->GetText().ToString();
        /** 登录服务器 */
        LoginServer(Nickname, Password);
}

/** 用户登录 */
void ULoginUserWidget::LoginServer(FString& Nickname, FString& Password)
{
        /** 创建要发送的数据 */
        FString Data;
        
        /** 创建Json写入器 */
        TSharedPtr<TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>> JsonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&Data);
        /** 开始写入对象数据 */
        JsonWriter->WriteObjectStart();
        /** 写入账号昵称 */
        JsonWriter->WriteValue("nickname", Nickname);
        /** 写入账号密码 */
        JsonWriter->WriteValue("password", Password);
        /** 结束写入对象数据 */
        JsonWriter->WriteObjectEnd();
        /** 关闭JsonWriter */
        JsonWriter->Close();

        /** 创建Http请求对象 */
        TSharedPtr<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
        /** 设置请求头 */
        HttpRequest->SetHeader("Content-Type", "application/json;charset=utf-8");
        /** 设置请求的URL */
        HttpRequest->SetURL("http://www.ujeat.com:7900/user/login-user");
        /** 设置请求方式为POST */
        HttpRequest->SetVerb("POST");
        /** 设置上传的JSON数据 */
        HttpRequest->SetContentAsString(Data);
        /** 设置请求成功后的响应事件 */
        HttpRequest->OnProcessRequestComplete().BindUObject(this, &ULoginUserWidget::ServerCompleteCallback);
        /** 处理请求 */
        HttpRequest->ProcessRequest();

        /** 显示进度控件 */
        LoadingCircle->SetVisibility(ESlateVisibility::Visible);
        /** 设置登录按钮不可用 */
        LoginBtn->SetIsEnabled(false);
}
/** 服务器响应的回调事件 */
void ULoginUserWidget::ServerCompleteCallback(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bIsSuccessful)
{
        
        /** 隐藏进度控件 */
        LoadingCircle->SetVisibility(ESlateVisibility::Hidden);
        /** 设置登录按钮可用 */
        LoginBtn->SetIsEnabled(true);

        /** 判断服务器返回状态 */
        if (!EHttpResponseCodes::IsOk(Response->GetResponseCode()))
        {
                /** 如果服务器未返回成功则返回 */
                return;
        }

        /** 创建服务器返回的内容 */
        FString Result = Response->GetContentAsString();
        /** 创建要解析的JSON对象 */
        TSharedPtr<FJsonObject> JsonObject;
        /** 创建Json解析器 */
        TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(Result);
        /** 解析Json */
        bool bIsParseSuccess = FJsonSerializer::Deserialize(JsonReader, JsonObject);
        /** 判断是否解析成功 */
        if (bIsParseSuccess)
        {
                /** 获取响应状态 */
                FString ResponseStatus = JsonObject->GetStringField("status");
                /** 获取响应信息 */
                FString ResponseMsg = JsonObject->GetStringField("msg");
                /** 获取响应的数据对象 */
                TSharedPtr<FJsonObject> Data = JsonObject->GetObjectField("data");
                /** 获取用户的id */
                FString Id = Data->GetStringField("id");
                /** 获取用户的昵称 */
                FString Nickname = Data->GetStringField("nickname");
                /** 获取用户的密码 */
                FString Password = Data->GetStringField("password");
                /** 判断是否登录成功 */
                if (!Id.IsEmpty())
                {
                        /** 登录成功则保存用户数据到GameInstance */
                        UCustomGameInstance* GameInstance = Cast<UCustomGameInstance>(GetWorld()->GetGameInstance());
                        /** 保存Id */
                        GameInstance->ContextMap.Add("id", Id);
                        /** 保存昵称 */
                        GameInstance->ContextMap.Add("nickname", Nickname);
                        /** 保存用户密码 */
                        GameInstance->ContextMap.Add("password", Password);
                        /** 切换关卡到主战场 */
                        /** 打开主关卡:注意此处打开关卡的路径 */
                        UGameplayStatics::OpenLevel(GetWorld(), TEXT("/Game/Maps/Map_War"));
                }
                else
                {
                        /** 设置服务器响应信息 */
                        ToastWidget->Msg->SetText(FText::FromString(ResponseMsg));
                        /** 显示Toast */
                        ToastWidget->SetVisibility(ESlateVisibility::Visible);
                }
        }
}

评分

参与人数 1鲜花 +3 收起 理由
admin + 3

查看全部评分


回复

使用道具 举报

7日久生情
2535/5000
排名
3382
昨日变化

2

主题

1780

帖子

2535

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
241666
好友
0
蛮牛币
10199
威望
0
注册时间
2017-9-6
在线时间
362 小时
最后登录
2018-6-7
发表于 2018-1-3 08:05:32 来自Mobile--- | 显示全部楼层
感谢分享

回复

使用道具 举报

7日久生情
2103/5000
排名
3201
昨日变化
2

0

主题

1463

帖子

2103

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
185339
好友
0
蛮牛币
2985
威望
0
注册时间
2016-11-20
在线时间
232 小时
最后登录
2018-6-15
发表于 2018-1-3 09:11:22 | 显示全部楼层
谢谢分享

回复

使用道具 举报

5熟悉之中
552/1000
排名
7145
昨日变化
1

2

主题

244

帖子

552

积分

Rank: 5Rank: 5

UID
229218
好友
1
蛮牛币
664
威望
0
注册时间
2017-6-28
在线时间
148 小时
最后登录
2018-6-15
发表于 2018-1-3 09:20:19 | 显示全部楼层
感谢分享

回复

使用道具 举报

排名
22184
昨日变化
5

0

主题

20

帖子

70

积分

Rank: 2Rank: 2

UID
236613
好友
0
蛮牛币
42
威望
0
注册时间
2017-8-9
在线时间
32 小时
最后登录
2018-1-3
发表于 2018-1-3 09:47:21 | 显示全部楼层
v5v5v5v5v5v5

回复

使用道具 举报

7日久生情
1796/5000
排名
2633
昨日变化
2

1

主题

892

帖子

1796

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
216583
好友
2
蛮牛币
3047
威望
0
注册时间
2017-4-7
在线时间
417 小时
最后登录
2018-6-15
发表于 2018-1-3 10:12:32 | 显示全部楼层
多谢分享

回复

使用道具 举报

5熟悉之中
567/1000
排名
6002
昨日变化

4

主题

225

帖子

567

积分

Rank: 5Rank: 5

UID
209710
好友
0
蛮牛币
1879
威望
0
注册时间
2017-6-15
在线时间
142 小时
最后登录
2018-6-13
发表于 2018-1-3 10:31:26 | 显示全部楼层
多谢分享,666

回复

使用道具 举报

7日久生情
3937/5000
排名
339
昨日变化

1

主题

379

帖子

3937

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
29828
好友
1
蛮牛币
1487
威望
0
注册时间
2014-6-16
在线时间
1946 小时
最后登录
2018-6-17
发表于 2018-1-3 12:52:40 | 显示全部楼层
谢谢分享

回复

使用道具 举报

5熟悉之中
530/1000
排名
14045
昨日变化
5

1

主题

234

帖子

530

积分

Rank: 5Rank: 5

UID
167799
好友
1
蛮牛币
395
威望
0
注册时间
2016-9-9
在线时间
245 小时
最后登录
2018-6-12
发表于 2018-1-3 13:40:12 | 显示全部楼层

感谢分享!!!

回复 支持 反对

使用道具 举报

3偶尔光临
253/300
排名
10040
昨日变化
2

0

主题

76

帖子

253

积分

Rank: 3Rank: 3Rank: 3

UID
182465
好友
0
蛮牛币
20
威望
0
注册时间
2016-11-9
在线时间
83 小时
最后登录
2018-4-26
发表于 2018-1-3 16:31:42 | 显示全部楼层
可以,最近在学ue4

回复 支持 反对

使用道具 举报

7日久生情
2571/5000
排名
408
昨日变化
2

0

主题

537

帖子

2571

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
88896
好友
0
蛮牛币
10032
威望
0
注册时间
2015-4-2
在线时间
536 小时
最后登录
2018-6-18
发表于 2018-1-3 17:29:18 | 显示全部楼层
文章好长,谢谢

回复

使用道具 举报

4四处流浪
316/500
排名
7975
昨日变化
1

0

主题

106

帖子

316

积分

Rank: 4

UID
251059
好友
1
蛮牛币
7
威望
0
注册时间
2017-10-27
在线时间
74 小时
最后登录
2018-4-11
发表于 2018-1-4 13:12:16 | 显示全部楼层
666666666666666666
[发帖际遇]: hellohahaha 发帖时在路边捡到 2 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

3偶尔光临
232/300
排名
8855
昨日变化
3

0

主题

33

帖子

232

积分

Rank: 3Rank: 3Rank: 3

UID
259144
好友
0
蛮牛币
354
威望
0
注册时间
2017-12-12
在线时间
85 小时
最后登录
2018-3-20
发表于 2018-1-11 16:58:04 | 显示全部楼层
[发帖际遇]: Unique丶 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复

使用道具 举报

7日久生情
2238/5000
排名
18907
昨日变化
1

2

主题

1857

帖子

2238

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
185807
好友
0
蛮牛币
2915
威望
0
注册时间
2016-11-22
在线时间
353 小时
最后登录
2018-6-8
发表于 2018-1-22 17:50:43 | 显示全部楼层
赞,学习了,谢谢分享

回复 支持 反对

使用道具 举报

7日久生情
2888/5000
排名
2692
昨日变化
10

0

主题

2008

帖子

2888

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
219676
好友
0
蛮牛币
2438
威望
0
注册时间
2017-7-12
在线时间
402 小时
最后登录
2018-6-18

活力之星

发表于 2018-3-21 18:36:34 | 显示全部楼层
[发帖际遇]: 夜雨微凉 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表