Giter Site home page Giter Site logo

MMORPG + Unreal 5 架构 about blog HOT 6 CLOSED

WangShuXian6 avatar WangShuXian6 commented on June 5, 2024
MMORPG + Unreal 5 架构

from blog.

Comments (6)

WangShuXian6 avatar WangShuXian6 commented on June 5, 2024

APP开发的GamePlay

APP开发的GamePlay.pdf

APP开发的GamePlay

UAPPGameInstance

Init()

初始化全局配置表
创建客户端实例
反射类注册
初始化客户端

Tick()

监测Tick

Shutdown()

销毁(Destroy)

GetStatId()

GetClient()

AAPPGameModeBase

AAPPGameStateBase

AAPPPlayController

BeginPlay()

控制台程序ConsoleCommand设置初始尺寸

Tick()

协程Tick(DetaTime)

EndPlay()

GThread::Destroy()

AAPPPlayerState

AAPPPawn

Data

UserData

APPData

Network

UAppClientObjectController

Init()
Tick()
Close()
RecvProtocol()

Protocols

LoginProtocols

Login
LoginSuccess
LoginFailed
Unregistered
WrongPassword

HallProtocols

GateLoginSucessful
HomePage
HomePageRequestSuccessful
HomePageRequestFailed
ProjectRequest
ProjectRequestSuccessful
ProjectRequestFailed
SubmitComments
SubmitCommentsSuccessful
SubmitCommentsFailed
GetComments
GetCommentsSuccessful
GetCommentsFailed
GetUser
GetUserSuccessful
GetUserFailed

AAPPHUD

AAllPlatformAPPHUD()

if PLATFORM_WINDOWS || PLATFORM_MAC
elif PALTFORM_IOS || PLATFORM_ANDROID

BeginPlay()

HomePagePtr->AddToViewport()

TSubclassOf<UUI_HomePage> HomePageClass

TWeakObjectPtr<UUI_HomePage> HomePagePtr

UI

UI_Base

构造UUI_Base(const FObjectInitializer& ObjectInitializer)

RecvProtocol()

循环绑定BindClientRecv()

绑定RecvProtocol()
协程循环执行BindClientRecv()

SetParent()

GetParent()

UWidget* MyParent

UI_Login

(UPROPERTY)UEditableTextBox* Account

(UPROPERTY)UEditableTextBox* Password

(UPROPERTY)UButton* SignInButton

(UPROPERTY)UButton* SignUpButton

(UPROPERTY)UTextBlock* LoginMes

NativeConstruct()

绑定Button
BindClientRecv()
解密本地账户DecryptionUser()

NativeDestruct()

IsAccountValid()

IsPasswordValid()

SignInGame()

SignUpGame()

LoginMsg()

DecryptionUser()

解密
自动登录:协程绑定SignInGame()

AES加密EncryptionUser()

RecvProtocol()接收服务器发送过来的协议

LoginSuccess

接收FNetUserInfo UserInfo

*FClientUserData::Get() = UserInfo

加密本地密码EncryptionUser()

LoginCallback()登录回调

接收网关地址

关闭原通道

从登录服务器切换到网关服务器(Init())

BindClientRecv()重新绑定

绑定主页

GateLoginSucessful

发送HomePage请求给网关

LoginCallback()登录回调

SetVisibility(Collapsed)

UI_HomePage

UPROPERTY(meta = (BindWidget))UButton* HomePageButton

(UPROPERTY)UUI_Login* LoginWidget

(UPROPERTY)UUI_Navigation* NavigationWidget

(UPROPERTY)UUI_Menu* MenuWidget

(UPROPERTY)UImage* LoaddingImage

(UPROPERTY)UScrollBox* ScrollListBox

(UPROPERTY)TSubclassOf<UUI_HomeDetailPage> HomeDetailPage

(UPROPERTY)TSubclassOf<UUI_ProjectDetailPage> ProjectDetailPage

TSubclassOf<UUI_UserDetailPage> UserDetailPage

NativeConstruct()

SetParent(this)
LoaddingImage

协程GetCoroutines()3s后Collapsed

HomePageButton->OnClicked.AddDynamic(HomePage())

NativeDestruct()

RecvProtocol()

HomePageRequestSuccessful

接收网关服务器的数据SIMPLE_PROTOCOLS_RECEIVE

导航InitButtons()

菜单

首页详情页HomeDetailPage

InHomeDetailPage = CreateWidget<UUI_HomeDetailPage>

InHomeDetailPage->SetParent(this)

WidgetReplace(InHomeDetailPage)

InHomeDetailPage->InitHomeDetailPage()

SP_ProjectRequestSuccessful

接收网关服务器的数据SIMPLE_PROTOCOLS_RECEIVE

InProjectDetailPage =

CreateWidget<UUI_ProjectDetailPage>

InProjectDetailPage->SetPostID()

InProjectDetailPage->SetParent(this)

WidgetReplace(InProjectDetailPage)

InProjectDetailPage->InitProjectDetailData()

SP_GetUser

接收网关服务器的数据SIMPLE_PROTOCOLS_RECEIVE

InUserDetailPage = CreateWidget<UUI_UserDetailPage>

InUserDetailPage->SetParent(this)

WidgetReplace(InUserDetailPage)

InUserDetailPage->InitUserDetailPage()

WidgetReplace()

ScrollListBox->ClearChildren()
ScrollListBox->AddChild(InReplaceWidget)

CreateProjectDetailPages()

向服务器发送请求SEND_DATA(SP_ProjectRequest, InID)
ScrollListBox->ClearChildren()

CreateUserDetailPage()

向服务器发送请求SEND_DATA(SP_GetUser, FClientUserData::Get()->UserID)
ScrollListBox->ClearChildren()

UFUNCTION() HomePage()

SEND_DATA(SP_HomePage)
ScrollListBox->ClearChildren()
NavigationWidget->CleanBox()

UI_ProjectPageList

UI_List

(UPROPERTY)UHorizontalBox* BoxList
(UPROPERTY)TSubclassOf<UUI_Node> NodeClass
RecvProtocol()
InitResources()

UI_Node* InNode -》Init

BoxList-》AddChildToHorizontalBox(InNode)

InitFrameworks()

UI_Node* InNode -》Init

BoxList-》AddChildToHorizontalBox(InNode)

CreateResourceNode()

InNode = CreateWidget()

InNode->InitNodeName

InNode->InitContent

InNode->InitPrice

InNode->InitID

InNode->SetParent

InNode->StartThumbnail

InFun(InNode)

UI_Node

(UPROPERTY)UTextBlock* NodeName
(UPROPERTY)UTextBlock* Content
(UPROPERTY)UTextBlock* Price
(UPROPERTY)UImage* Thumbnail
(UPROPERTY)UButton* LinkButton
InitNodeName()
InitContent()
InitPrice()
InitID()
InitThumnail()
StartThumbnail()
UFUNCTION() DownloadComplete()
UFUNCTION() OnLinked()

InHomePage = GetParent<UUI_HomePage>()

InHomePage->CreateProjectDetailPages(NodeID)

UI_InebrietyList

UI_FrameworkPageList

Common

UI_Menu

UButton* UserButton
NativeConstruct()

UserButton->OnClicked.AddDynamic(OnLinked)

OnLinked()

InHomePage = GetParent<UUI_HomePage>()

InHomePage->CreateUserDetailPage()

UI_Navigation

(UPROPERTY)UWrapBox* Box;
(UPROPERTY)TSubclassOf<UUI_Button> ButtonClass
InitButtons()
NativeConstruct()
NativeDestruct()
void CleanBox()

Box->ClearChildren()

Element

UI_Button

(UPROPERTY)UTextBlock* ButtonName

(UPROPERTY)UButton* ButtonWidget

UFUNCTION() OnClicked()

NativeConstruct()

ButtonWidget绑定OnClicked

SetID()

SetButtonName()

UI_Slide

(UPROPERTY)UFilmstrip* FilmstripInst
(UPROPERTY)UButton* NestButton
(UPROPERTY)UButton* PreviousButton
NativeConstruct()

FilmstripInst->OnClickedLinkEvent绑定敲击事件 Link()

NestButton->OnClicked

PreviousButton->OnClicked

InitFilmstrip()

从NetFilmstrips中提取ImgURL

HTTP代理绑定下载

UFUNCTION() DownloadComplete()

图片转换Uint8ArrayToTexture2D

FilmstripLinkInfos.Texture赋值

FilmstripLinkInfos.LinkURL赋值

UFUNCTION() AllDownloadComplete()

FilmstripInst->AddTextures()

UFUNCTION() Link()
UFUNCTION() Nest()

FilmstripInst->Nest()

UFUNCTION() Previous()

FilmstripInst->Previous()

(UPROPERTY)TArray FilmstripLinkInfos
FNetFilmstrips NetFilmstrips
UFilmstrip插件

(UPROPERTY)TArray LinkInfo

(UPROPERTY)float ShowTime

(UPROPERTY)float ChangeTime

(UPROPERTY)FFilmstripPlayType FilmstripPlayType

(UPROPERTY)FOnClickedLinkEvent OnClickedLinkEvent定义动态多播代理敲击事件

UFilmstrip()构造

初始化ShowTime

初始化ChangeTime

初始化FilmstripPlayType

初始化裁剪模式clipping

UFUNCTION() InitResources()

判断时间句柄是否有效Handle.IsValid()

ClearTimer(Handle)

判断LinkInfo是否有值

AddTextures()

UFUNCTION()AddTextures()

判断MyFilmstrip是否有效

MyFilmstrip->ClearChildren()

Brushs.Empty()

遍历AddTexture()

UFUNCTION()Previous()

MyFilmstrip->Previous()

UFUNCTION()Nest()

MyFilmstrip->Nest()

AddTexture()

添加图片

设置图片格式

MyFilmstrip设置图片和LinkURL

SlateHandleLinkClicked()

OnClickedLinkEvent.Broadcast()执行动态多播代理敲击事件广播

virtual TSharedRef RebuildWidget() override

初始化MyFilmstrip

ShowTime
ChangeTime
PlayStyle
OnLinkClicked代理绑定SlateHandleLinkClicked()

SetTimer(Handle, this, &UFilmstrip::InitResources, 0.1f)

返回MyFilmstrip共享引用

virtual void ReleaseSlateResources(bool bReleaseChildren)

MyFilmstrip.Reset()

Brushs.Empty()

ClearTimer(Handle)

TSharedPtr MyFilmstrip

TArray Brushs

FTimerHandle Handle

FilmstripPlayType

FilmstripPlayType

Default

Surround

FilmstripLinkInfo

(UPROPERTY)UTexture2D* Texture

(UPROPERTY)FString Link

SFilmstrip

SLATE_ARGS

SLATE_BEGIN_ARGS

_ShowTime
_ChangeTime
_PlayStyle

SLATE_ARGUMENT

ShowTime
ChangeTime
PlayStyle

SLATE_EVENT

OnLinkClicked

SLATE_END_ARGS

Construct()

ShowTime = InArgs._ShowTime

ChangeTime = InArgs._ChangeTime

PlayStyle = InArgs._PlayStyle

OnLinkClicked = InArgs._OnLinkClicked

SetImage()

TSharedPtr Image = SNew(SImage);

Image->SetImage(InImage);

获取数量

设置位置

设置图片大小

收集Slot

SNew(SButton)

OnClicked绑定OnClickedLinked()

ContentPadding(FMargin())

HAlign(EHorizontalAlignment::HAlign_Fill)

VAlign(EVerticalAlignment::VAlign_Fill)

Content()

Image.ToSharedRef()

设置Slot当前阶段

OnPaint()

PlayType::Default

PlayType::Surround

Previous()

Nest()

TArray MySlots

OnClickedLinked()

执行OnLinkClicked.Execute()

单播代理FOnLinkClicked OnLinkClicked

float ShowTime

float ChangeTime

FFilmstripPlayType PlayStyle

float ChangeDeltaTime

bool bHasImage

bool bFlip

FDrawElement

FSlot* Slot

float CurrentStage

float ShowTimeCount

float EndStage

float StartPos

细节面板

UI_HomeDetailPage

(UPROPERTY)UUI_Slide* SlideWidget

(UPROPERTY)UUI_List* ProjectWidget

(UPROPERTY)UUI_List* FrameworkWidget

(UPROPERTY)UUI_List* InebrietyWidget

NativeConstruct()

SetParent(this)

InitHomeDetailPage()

SlideWidget->InitFilmstrip()
ProjectWidget->InitResources()
InebrietyWidget->InitResources()
FrameworkWidget->InitFrameworks()

UI_ProjectDetailPage

(UPROPERTY)

UUI_TutoriaSystem* Video
UImage* AuthorAvatar
UTextBlock* AuthorIntroduce
UButton* BuyButton
UCheckBox* DocumentBox
UCheckBox* DownloadBox
UCheckBox* CommentBox
UCheckBox* VideoCatalogueBox
UWidgetSwitcher* Switcher
UUI_ArticleDisplayPage* ArticleDisplayPage
UUI_CatalogueDisplayPage* CatalogueDisplayPage
UUI_CommentDisplayPage* CommentDisplayPage
UUI_DownloadDisplayPage* DownloadDisplayPage

NativeConstruct()

AddDynamic()
Boxs.Add()
SetParent(this)

InitProjectDetailData()

AuthorIntroduce->SetText()
ArticleDisplayPage->InitArticleDetailPage()
CatalogueDisplayPage->InitCatalogueDisplay()
DownloadDisplayPage->InitDownloadDisplayPage()
CommentDisplayPage->SetPostID()
CommentDisplayPage->InitCommentDisplayPage()

PlayVideo()

Video->PlayMediaByNet()

SetPostID ()

CheckBox OnCheckStateChanged绑定函数

DocumentDetail()

ResetCheckBox()

DocumentBox->SetCheckedState()

Switcher->SetActiveWidgetIndex(0)

DownloadDetail()
CommentDetail()
VideoCatalogueDetail()

ResetCheckBox()

遍历Boxs
SetCheckedState(ECheckBoxState::Unchecked)

Buy()

TArray<UCheckBox*> Boxs

uint32 PostID

uint32 AuthorID

UI_InebrietyPage

UI_FrameDetailPage

UI_UserDetailPage

UImage* HeadPortrait

UTextBlock* UserName

UTextBlock* UserID

UCheckBox* ResourceBox_96

UCheckBox* GameBox_188

UWidgetSwitcher* Switcher

UWrapBox* ResourceList

UWrapBox* GameList

TSubclassOf<UUI_Node> NodeClass

NativeConstruct()

ResourceBox_96->OnCheckStateChanged.AddDynamic(Resource)
GameBox_188->OnCheckStateChanged.AddDynamic(Game)

Resource(bool IsChecked)

GameBox_188->SetCheckedState(Unchecked)
Switcher->SetActiveWidgetIndex(0)

Game(bool IsChecked)

ResourceBox_96->SetCheckedState(Unchecked)
Switcher->SetActiveWidgetIndex(1)

InitUserDetailPage()

UUI_List::CreateResourceNode()
UserName->SetText
UserID->SetText

UI_RechargeDetailPage

UI_PurchaseVerification

Element

UI_ArticleDisplayPage

UPROPERTY()UWebBrowser* WebBrowserPtr

UPROPERTY()FString DummyURL

UUI_ArticleDisplayPage()

InitArticleDetailPage()

WebBrowserPtr->LoadString()

UI_CatalogueDisplayPage

UPROPERTY(meta = (BindWidget))UVerticalBox* ListBox

UPROPERTY(EditDefaultsOnly, Category = UI)TSubclassOf<UUI_CatalogueDisplaySlot> CatalogueDisplaySlots

InitCatalogueDisplay()

InExpandableArea = NewObject()
HeaderText = NewObject()
InList = NewObject()
InExpandableArea->SetContentForSlot(header,Body)
InCatalogueDisplaySlot = CreateWidget<UUI_CatalogueDisplaySlot>()
InList->AddChildToVerticalBox(InCatalogueDisplaySlot)
InCatalogueDisplaySlot->InitCatalogueDisplaySlot()
父类注册InCatalogueDisplaySlot->SetParent(this)
ListBox->AddChildToVerticalBox(InExpandableArea)

ResetSlot()

遍历ListBox
遍历CatalogueDisplaySlots
设置SetCheckedState()

UI_CommentDisplayPage

UPROPERTY(meta = (BindWidget))UUI_CommentInput* CommentInput

UPROPERTY(EditDefaultsOnly, Category = UI)

TSubclassOf<UUI_IeaveMessage> IeaveMessage

UPROPERTY(EditDefaultsOnly, Category = UI) int32 MaxCommentNum

UPROPERTY(meta = (BindWidget))

UVerticalBox* CommentList

UPROPERTY(meta = (BindWidget))

UButton* PreviousButton

UPROPERTY(meta = (BindWidget))

UButton* NestButton

本地可识别数据struct FCommentDataNode

UUI_CommentDisplayPage()

初始化MaxCommentNum(5)
初始化CurrentPageCount(0)

NativeConstruct()

BindClientRecv()
PreviousButton->OnClicked.AddDynamic(Previous)
NestButtonButton->OnClicked.AddDynamic(Nest)
CommentInput->SetParent(this)

NativeDestruct()

Remove(DelegateHandle)

RecvProtocol()

SP_SubmitCommentsSuccessful
SP_GetCommentsSuccessful

接收评论内容和数量

InitCommentDisplayPage()

BindClientRecv()

InitCommentDisplayPage()

判断评论所处的位置

设置PreviuosButton和NestButton可见性

CommentList->ClearChildren()
将网络数据转成本地可识别数据NetCommentsToCommentDataNode()
遍历本地可识别数据
RecursionSpawnWidget递归动态生成ExpandableArea
CommentList->AddChildToVerticalBox(ExpandableArea)

SetPostID()

CommentInput->SetPostID()

SetCommentInputReplyID()

SetCommentAuthorName()

CommentInput->SetCommentObject()

ActivateCancelButton()

CommentInput->ActivateCancelButton()

FORCEINLINE const GetMaxCommentNum()

FORCEINLINE const GetCurrentPageCount()

UFUNCTION() Previous()

CurrentPageCount--
向服务器发送GetComments请求

UFUNCTION() Nest()

CurrentPageCount++
向服务器发送GetComments请求

内部函数

NetCommentsToCommentDataNode()

if CommentParentID == 0)直接赋值

else递归RecursionNetToNode()

RecursionSpawnWidget

动态生成ExpandableArea

动态生成HorizontalBox

动态创建UI_LeaveMessage

创建UI_LeaveMessage成功

SetParent()

SetCommentID

SetCommentatorID

SetHeadPortrait

SetAuthorName

SetCommentAndDate

SetCommentContent

生成间隔Spacer

HorizontalBox->AddChildToHorizontalBox(Spacer)

HorizontalBox->AddChildToHorizontalBox(UI_LeaveMessage)

设置HorizontalBoxSlotSize

如果该评论有回复动态生成VerticalBox

遍历回复
递归动态生成NewExpandableArea
VerticalBox->AddChildToVerticalBox(NewExpandableArea)

ExpandableArea设置身体VerticalBox

ExpandableArea设置头部HorizontalBox

FDelegateHandle DelegateHandle

uint32 PostID

uint32 CurrentPageCount

UI_DownloadDisplayPage

UPROPERTY(meta = (BindWidget)) UImage* Propaganda

UPROPERTY(meta = (BindWidget)) UWebBrowser* CourseBrowser

UPROPERTY(meta = (BindWidget)) UWebBrowser* FrameworkBrowser

UPROPERTY(meta = (BindWidget)) UButton* CourseLinkButton

UPROPERTY() FString CourseLinkURL

NativeConstruct()

CourseLinkButton绑定OnLink事件CourseLink

InitDownloadDisplayPage()

HTTP代理绑定DownloadComplete()
执行下载Propaganda
FrameworkBrowser->LoadString()

UFUNCTION() DownloadComplete()

InTexture = Uint8ArrayToTexture2D()
Propaganda->SetBrushFromTexture(InTexture)

UFUNCTION() CourseLink()

CourseBrowser->LoadURL(CourseLinkURL)
Element

UI_CatalogueDisplaySlot

UPROPERTY(meta = (BindWidget)) UCheckBox* VideoSectionBox;

UPROPERTY(meta = (BindWidget))

UTextBlock* VideoName

NativeConstruct()

InitCatalogueDisplaySlot()

URL赋值
设置VideoName

SetCheckedState()

SetCheckedState()

UFUNCTION()Section()

CatalogueDisplayPage = GetParent<UUI_CatalogueDisplayPage>()
CatalogueDisplayPage->ResetSlot(this)
ProjectDetailPage = GetParent<UUI_ProjectDetailPage>()
ProjectDetailPage->PlayVideo(URL)

FString URL

UI_CommentInput

UPROPERTY(meta = (BindWidget)) UTextBlock* CommentObject

UPROPERTY(meta = (BindWidget))

UButton* CommetButton

UPROPERTY(meta = (BindWidget))

UMultiLineEditableTextBox* EditableTextBox

UPROPERTY(meta = (BindWidget))

UButton* CancelCommetButton

UUI_CommentInput(const FObjectInitializer& ObjectInitializer)

初始化PostID
初始化ReplyID

NativeConstruct()

CommetButton->OnClicked.AddDynamic(OnClickCommet)
EditableTextBox->OnTextCommitted.AddDynamic(OnTextCommittedEditableText)
CancelCommetButton->OnClicked.AddDynamic(OnClickCancelComment)

SetPostID()

SetReplyID()

SetCommentObject()

CommentObject->SetText()

ActivateCancelButton()

CancelCommetButton->SetIsEnabled(true)

UFUNCTION() OnClickCommet()

InCommentDisplayPage = GetParent<UUI_CommentDisplayPage>()
InCommentDisplayPage->GetMaxCommentNum()
InCommentDisplayPage->GetCurrentPageCount()
SEND_DATA(SP_ProjectRequest, PostID, ReplyID, FClientUserData::Get()->UserID,MaxCommentNum,CurrentPageCount,LeavingMessage)
清空 LeavingMessage

UFUNCTION() OnClickCancelComment()

ancelCommetButton->SetIsEnabled(false)
CommentObject->SetText()

UFUNCTION() OnTextCommittedEditableText()

LeavingMessage = InText
清空EditableTextBox

uint32 PostID

uint32 ReplyID

FString LeavingMessage

UI_IeaveMessage

UPROPERTY(meta = (BindWidget))

UTextBlock* AuthorName

UPROPERTY(meta = (BindWidget))

UImage* HeadPortrait

UPROPERTY(meta = (BindWidget))

UTextBlock* CommentAndDate

UPROPERTY(meta = (BindWidget))

UTextBlock* CommentContent

UPROPERTY(meta = (BindWidget))

UButton* ReplyButton

NativeConstruct()

ReplyButton->OnClicked.AddDynamic(OnClickReply)

SetAuthorName()

SetHeadPortrait()

SetCommentAndDate()

SetCommentContent()

SetCommentID()

SetCommentatorID()

UFUNCTION() OnClickReply()

CommentDisplayPage = GetParent<UUI_CommentDisplayPage>()
CommentDisplayPage->SetCommentInputReplyID (CommentID)
CommentDisplayPage->SetCommentAuthorName(AuthorName->GetText())
CommentDisplayPage->ActivateCancelButton()

uint32 CommentID

uint32 CommentatorID

FClientUserData单例

FClientUserData* Get()

Destroy()

重载操作符=

uint32 UserID

FString UserEmail

FString UserURL

FString UserAccount

FString UserName

static FClientUserData* UserData

struct FCommentDataNode

uint32 CommentID

uint32 CommentatorID

UTexture2D* CommentatorImag

FString CommentData

FString CommentatorName

FString CommentContent

TArray<TSharedPtr> Node

重载操作符=:FCommentDataNode& operator=(const FNetComment& InNetComment)

递归网络数据RecursionNetToNode()

NetDataStruct

通用的节点数据FNetData

uint32 ID

TCHAR ImgURL[TCHAR_MAX_SIZE]

通用的节点数据FNetNodeData

TCHAR Name[TCHAR_MAX_SIZE]

首页详情数据结构FNetHomePageData

导航

导航FNetButton

TCHAR Name[TCHAR_MAX_SIZE]

uint32 ID

菜单

幻灯片

幻灯片FNetFilmstrip

TCHAR LinkURL[TCHAR_MAX_SIZE]

资源

资源节点FNetResourcesData

uint32 DownloadCount

uint32 Price

游戏

资源节点FNetResourcesData

uint32 DownloadCount

uint32 Price

文章

文章节点FNetFrameworkData

TCHAR Introduction[TCHAR_MAX_SIZE]

项目详情数据结构FNetProjectDetailPageData

视频目录FNetVideoCatalogue

TCHAR VideoURL[TCHAR_MAX_SIZE]

评论FNetComment

uint32 CommentParentID
uint32 CommentID
uint32 CommentatorID
TCHAR CommentatorURL[TCHAR_MAX_SIZE]
TCHAR CommentDate[TCHAR_MAX_SIZE]
TCHAR CommentatorName[TCHAR_MAX_SIZE]
TCHAR CommentCotent[TCHAR_MAX_SIZE_2]

int32 CommentNum

下载

FNetDownloadData NetDownloadData

TCHAR CourseURL[TCHAR_MAX_SIZE]

TCHAR PropagandaURL[TCHAR_MAX_SIZE]

FString DownloadContent
FString DescriptionContent

文章FNetAticleContent

用户页数据FNetUserDetailPage

uint32 UserID

FString UserName

FString ImageURL

FNetResourcesDatas ResourcesDatas

FNetUserInfo

uint32 UserID

FString UserEmail

FString UserURL

FString UserAccount

FString UserName

from blog.

WangShuXian6 avatar WangShuXian6 commented on June 5, 2024

week1 笔记

1.[安装UE5源码版本]

安装VS2019到C盘

选择语言包

中文
英文

image

image

image

image

image

安装UE5源码版

从官网下载源码版本,解压时注意修改文件名短一点,不然安装时会报错

image

image

打开UE5项目文件后提示什么安什么比如

image

编译

选择为模式然后进行编译

image

2.[安装番茄插件]

如果安装前已经有番茄插件,执行卸载,然后在卸载后检查注册表有番茄英文名的删掉.然后再进行重新安装.安装好后替换放入两个破解文件即可,注意禁用自动更新

image

3.[安装UE5相关开发插件]

新建一个项目

将这个目录底下除了文件夹以外的文件都复制到这个文件夹的上一级

然后右键项目文件重新生成项目后如果报错在项目根目录底下新建一个txt文件改为bat文件来进行使用.在里面粘贴进去报错第一行.然后修改一下路径.在最终执行exe上级再加一个文件夹路径

image

如果进去编译新建项目还是报错的话,在调试最后的位置加入如下字段-zm140

image

安装四个插件

image
image
image
image

将这四个插件安装到引擎中的插件目录中

image

注意插件都是一个文件夹然后里面都是文件,注意检查文件层级.然后最后用生成来进行生成
image

引擎生成后再使用项目生成
image

最后在代码中再生成一次UE5引擎

4.准备db和网关和登陆服务器启动结构

在该目录下复制3个BlankProgram

image

登录服务器,是负责转发的.验证我们当前的玩家是否可以登录服务器

image

网关服务器,也是用来做转发的,为了安全.捏脸的数据保存.创建角色之类的

image

数据库服务器,用来负责处理数据的[读写数据库]

image

替换目录下的BlankProgram为当前服务器文件夹的名字.然后cpp和Build等文件里的对应字段[类名,其他空白文件名等]也要修改成当前服务器文件名

用引擎的生成生成一下.然后在Sln工程文件里,Build每个服务器一遍.
image

使用批处理的方式按顺序启动db,网关和登录服务器.Build后在该目录底下可以找到对应服务器的启动程序.然后可以作为批处理的路径

image

image
image
image

image

间隔0.5秒去启动服务器

image

5.数据库服务器架构概念

初始化读取本地配置

MySql

初始化MySql配置数据

端口用户密码等等

分布式插件[管理Socket]

服务器IP可以省掉,只设置端口就可以
客户端IP不能省,因为需要知道连接的服务器IP.
用的是预分配方案不考虑内存泄漏

注册(对象注册),绑定一些代理

Tick不断的检测消息(是一个死循环,因为服务器一旦开启不考虑关掉)

把服务器清掉

删除其他的类.做一些清理

6.架构db服务器全局配置

MMOARPGdbServer

定义接口变量,结构体[配置表结构]

image
image

配置表单例

image

image
image

7.部署远程数据库的准备工作

下载安装PHPStudy

其中包含部署网站要用的一些环境

部署WordPress

用来开发网站,可以帮我们生成一些用户信息,不用手动.用的是他里面的数据库

部署到远程电脑上[本机也可以,或者局域网和阿里云之类的也可以,但是学习阶段用本机就够了]

8.手把手部署远端WP数据库

官网下载PHPStudy(小皮)最新版

在面板里安装7.4.3的php(以后根据环境选最新)然后记得把网站里的php切换成这个版本.原来低版本的卸载不卸载无所谓

运行SQL和阿帕奇

官网下载WorldPress当前最新版本

解压wordpress数据包

image

放到PHPStudy的WWW目录下
image

改名为wp(其实叫什么都可以,这里主要是为了简写然后访问的时候好输入)注意解压的文件是所有文件直接就在wp底下.中间不要再有中间文件夹层级,不然后面访问wp页面的时候会报错

然后在浏览器输入地址开始进行安装

image

安装到这一步保持和下面新建的数据库一致

image

这些都按自己的需求来填就行了,没必要一摸一样.如果是实际项目就别用弱密码了.不过这个后面也可以改
image

最后可以登录看一下

image

官网下载Navicat的Premium版本

数据库可视化操作用的(用别的可视化数据库软件也可以,但是新手建议跟着老师用这个)

image

首次链接会填写链接名(随便填)还有密码,教学里是和用户名一致都是root,别的保持默认就可以

然后右键新建数据库

image

在上面worldpress安装完成后可以刷新看一下wp的用户表里有没有值

image

正常的话应该是有一条数据的
image

9.架构数据库服务器

步骤

初始化

注册反射类

Tick

销毁

创建

image

这个类是用来暴露在外面由用户来进行配置的.如何发送消息,消息里有那些内容.服务端和客户端都会有这样一个对象

image

继承自USimpleController主要是为了支持反射

image

image
注意模块包含

image
image

运行后会发现在该目录下产生配表文件.首次生成可能不正确.如果不正确的话请手动改正成后面那样.本机配置暂时不用改
image

数据库配置文件,DB得改成wp_server

image

10.分布式插件架构讲解

UPD构架

服务器(Manage)

connect(状态)

channel(主通道)

object(对象,反射)用户可以在上面写一些用户行为

channel_1

...

connect2(状态)服务器的一个connect对应一个客户端.服务器可以有多个connect.当释放掉(客户端关闭以后.这个connect也会关掉)
...

Manage

这一步创建的就是Manage也就是上面的服务器或者之后的客户端

image

Manage初始化过程

创建Socket

申请缓存区

绑定端口(服务器)

开启监听模式

链接服务器,进行第一次握手(客户端)
image

可以去知乎看分布式插件的介绍.里面也有详细讲解

11.架构数据库服务器读和写

MySQL插件

对象

一个对象专门用来写

提交到服务器

Post

一个对象专门用来读

从服务器拿下来然后发到UE5客户端

Get

创建读写Object和对应接口

image

在初始化中创建读写实例

image

在Close中将读写实例销毁
image

Post给数据库写入对象(其实就是数据库查询)

image

获取数据库信息

image

在Init的最后面加入这些语句进行测试.看是否能正常获取到数据库的信息.如果获取征程.结果不为空而且在CMD里会正常打印你的用户信息

image

如果是多台电脑只要不是在本机测试的情况下获取为空的话去数据库的用户表里复制第一行到最后一行.然后替换Host为%号.这样所有的用户权限都相当于打开了.这样就可以正常获取了

image

12.分离数据日志

这节课没啥难的.就是把原来文件里的这一句提出来,然后单独放一个文件里.然后原来文件里再包含这个头文件就行了.这样做就是单纯为了这个独立程序里的其他文件也可以调用这个日志打印的东西

image

调用的时候的例子

image

13.架构网关服务器

网关可以理解成就是个把门的,过滤数据的

image

列表List
image

然后从第二步开始创建网关和db的实例初始化等操作.其实和dbServer那一节基本是一样的.就是Object里不带数据库操作了

image

注意第三步用的Object不是同一个.需要分开.虽然代码一样.这里的Object是去掉数据库部分的.剩下的代码都是基本的插件里的执行父类

db服务器指定端口

image

登录服务器构架

image

大致构架,这个构架有点问题.具体看下一课

14.架构登陆服务器

登录服务器构架

image

服务器(客户端)列表
image

创建对应需要的Object

image

里面的代码结构都一样.这里我只放一个.实现调用一下父类就行了.还有别忘了剥离Log系统

image

代码实现上和dbServer还有GateServer差不多.就是注意客户端和服务器创建Manage里面的链接状态.服务器是监听.客户端是连接

image

至此整个分布式的构架就算搭好了

服务器的Build和Target设置和dbServer基本一致,只是不包含数据库插件

15.架构客户端网络驱动

客户端网络驱动器简单构架理解

image

使用GameInstance来做这一部分

初始化
循环
结束(销毁)
和之前的服务器比少了Object反射那一部分

创建

image

如果报错的话应该是HTTP插件那边有个报错,通过报错的参数,用Alt+G找到声明的地方.把注释调换一下就可以了

image

把创建的GI选择上.如果没有的话.重启一下UE5就好了

image

具体实现

image
image

注意GameInstance是不带Tick.按照老师说的是用TStatId后面要怎么做一下才可以(这个我得拿去完了问一下老师)

初始化拆开

创建Socket

链接服务器

防止握手过程中失败,保证握手成功之后再保持长链接.再一个就是在握手前对客户端进行一个绑定

注意这一节课还需要在UE5中包含人宅老师的这几个插件.HTTP主要是用来下载图片的

image

注意这里也要包含,因为客户端网络驱动用了

image

这节课把头显的模块还有角色里涉及到头显的头文件还有代码都注释掉

客户端(Manage)

connect(状态)[客户端只有一个]

channel(主通道)

object(对象,反射)用户可以在上面写一些用户行为

channel_1

...

CoreUObject的包含是因为编译报错了.找到报错的那一行代码.然后找到这个文件.然后看最上级模块是CoreUObject[文件夹名]所以包含

from blog.

WangShuXian6 avatar WangShuXian6 commented on June 5, 2024

week2 笔记

1.部署登录Gameplay框架

loding的显示条件和服务器与客户端状态进行对应

image

登录的GamePlay构架

image

UI是一方面主要是用来显示服务器和客户端状态的

为什么要创建UI_Base
image

具体实现

image

创建GameMode

关联HUD
关联Pawn
关联PlayerController

创建Controller(用来做输入用的,比如触摸点击或者文字输入)

在构造里打开鼠标显示

创建Pawn(主要是为了断绝WASD这样的输入后角色还能移动的问题)

创建HUD(作为登录的UI显示用)

HUD里生成登录的UI

创建UI

创建UI_Base(这样里面可以放一些通用方法类)

创建UI_LoginMain继承自UI_Base

创建Login用的Map

Map加载登陆的GameMode

2.获取前期握手登录状态

登录这块客户端的构架就是UI

image

1.部署协议接收通道(接受服务器的回应)

2.部署绑定握手能不能握成功的检测

3.宏文件

确保GameInstance是准备好的再去和UI进行代理绑定

image

客户端

UI_Base

image

UI_LoginMain

image

image

就是按照之前的逻辑来实现了一下.逻辑顺序看LoginMain的构造里的调用顺序就基本明白了

3.架构Cpp登陆UI

登录窗口的逻辑

image

UI_Base模板函数返回任意父类类型.设置父类的接口作用应该是每个继承自该基类的UI都有一个设置上的父类.这里的作用还是为了让UI_Login去快速调用UI_LoginMain的接口.但是其实UI_LoginMain并不是UI_Login的父类.这个子父关系更像是Unity里的获取父类组件

image

UI_LoginMain

image
image

UI_Login

image

仔细看逻辑都是执行在Main(父类里)

image

4.分离通用的协议模块

为什么要分离通用的协议模块

image

在MMOARPG里创建一个新的空白插件.创建这个插件作为通用工具.(其实是一个模块,但是做成插件好调用.这个插件不具备可移植性)是给几个服务器客户端啥的进行通用的.[最后注意模块包含.引擎模块是肯定不包含的.省下就是SNC插件包含如图]

image

然后把这个插件连根移到UE的插件目录底下,重新生成引擎和项目文件.

然后启动在项目里启用插件.然后注意这一部分重新启动项目后可能需要再生成一遍引擎的部分文件

在项目的模块里包含这个插件(本质上不是插件,我们只是用到它的一个模块)

在插件里给登录协议加入两个请求,登录请求和响应请求

image

MMOARPG包含该插件模块

网关包含该插件模块

DB服务器包含该插件模块

登录服务器包含该插件模块

网络协议分离,一套东西多个服务器客户端共同使用.该插件不具备可移植性.因为本质是模块

5.发送登录请求到数据库验证

交互逻辑

image

这节课完成的逻辑,主要就是发送登录请求到dbServer

image

视口点击登录发送的接口其实之前的课已经做了.这里需要的是加入协议进行发送(传入账号密码)

image

判断平台来进行写宏.PC和移动平台的宏不一样必须这样做,区别主要是后面的参数

image

点击以后先是发送到登录服务器,接收账号密码.注意登录协议保持一致.提出地址给db客户端转发.并打印Log

image

db客户端之前就已经设置好端口了.端口是db服务器的.
image

这里没有做具体逻辑.但是执行父类了.应该是插件就做转发了

image

最后转发到dbServer打印信息.其实和登录服务器的逻辑基本一样(仅限于这节课).下节课开始dbServer要开始做验证密码是否正确的逻辑了

image

6.数据库如何验证wp登录密码

这节课在做什么的逻辑

image

dbServer拿到账户密码后开始验证

image

1.看代码逻辑,首先是用SQL语句获取账户ID.这个是从真正的数据库里取到的
2.然后获取对应的加密密码
3.然后是用全局配置获取服务器公网IP
4.将公网IP,还有用户加密密码,拿到的客户端那边发送过来的密码.地址.端口.通道.还有完成密码验证后的回调代理传入.向wp服务器发送一个验证密码的请求
PS.如果没有取到结果或者是取到的结果没有值,均发送错误响应.ELoginType是共用登录类型枚举(自己加的)

wordPress需要安装的老师的插件,用来做密码验证的

image

UserID是用户ID

EncryptedPassword是加密了的密码

Password是密码

IP是网关IP

Port是网关端口

Channel是网关通道

注意安装时的头文件包含报错

密码验证应该是调用了WP的验证

image

这个安装注意是要进入WorlPress的后台进行安装的

7.如何通过HTTP向PHP进行通信

这节课主要讲的是打通下面这条线

image

从dbServer接收开始回调开始

image

执行回调里解析,验证,并最后响应

image

db客户端接收,然后转发给登录服务器.这里注意转发到服务器用是SERVER.转发到客户端用的是CLIENT[这里的响应的网关地址就是服务器当初发过去的地址.一路转发过来地址是保持对应的,不然没办法回调回去]
image

客户端登录回调.注意是响应不是请求

image

8.验证登录请求到服务器响应流程

修改第一个错误,是响应不是请求协议.不然接收不到

image

第二个错误.这里转发到服务器应使用SIMPLE_SERVER_SEND

image

转发或者发送给服务器用SIMPLE_SERVER_SEND

转发或者发送给服务器用SIMPLE_CLIENT_SEND

第三个忽略的点,这里要用两个相同的账户String去接数据.不然email没地方去.输入也会变成乱码

image

最后说是之后的课要做数据本地化.用xml或者json之类的来接服务器的数据之类的

9.用户数据Json解析

构架及流程

image

创建用户数据并加入导出宏提供使用

image

在GameInstance存储用户数据

image

写入Json的接口.写入并序列化成字符串

image

反序列化并读取Json的接口

image

Json的数据结构

image

10.服务器的负载均衡架

负载均衡构架,除了构架注意序号.基本是实现顺序

image

1.添加网关协议,请求和响应(这里注意协议号别重了.之前已经有0和1了)

image

2.配置表(网关状态)

image

网关客户端(登录服务器里)每秒请求更新一次网关状态

image

网关服务器收到请求,返回响应.带着网关状态
image

网关客户端响应接收状态

image

3.4两步一起

db客户端判断网关选择最优最后返回并转发给服务器

image

更换选择逻辑

image

11.测试整套客户端登录服务器的流程

这节课的逻辑.主要就是从服务器拿到数据并判断响应

image

1.dbServer取到用户数据压为字符串发送成功登陆响应

image

数据解析之前做一次清理

image

2.db客户端接收dbServer的String,然后验证并加入网关信息发送给登录服务器

image

3.客户端做响应然后把数据解析到GameInstance的用户数据里.这里的网关是全局变量.本地需要存储一个将来做动画用的.

image

12.MD5和AES存储账户和密码

加密什么时候开始以及加密构架

image

加密解密的接口都写在了UI_Login里

image

在UI_LoginMain里的构造调用读取解析账号

image

加密的具体逻辑.其中最后面存储路径时之前删除该路径是关键.注意文件夹不要设定在根目录.要加个User.不然整个项目都给你删掉
image

在UI_LoginMain里的登录成功响应里调用开始对该路径进行文件加密写入

image

读取文件并解密然后给输入框赋值的逻辑.相当于实现了记住账号密码
image

这一步是递归获取该路径下的所有文件和文件夹.最后两个参数是控制是否获取文件和文件夹的

image

AES加密时的怖位逻辑及原因

image

13.控件如何播放动画

创建登录显示和淡出的动画

登录淡入

image

在登录主界面构造的时候淡入

image

登录成功淡出

image

在登录成功的地方里面调用淡出

image

注意做动画的时候专门有个轴是控制在动画过程中不能点击输入之类的

把Log的UI单独提出来了.然后创建了一个提示动画

创建了一个C++父类

image

image

简单做了一下实现

记得要给蓝图的Log替换父类.然后再LoginMain里的C++和蓝图两个地方把组件都替换成新剥离的Log

加入播放动画和设置当前组件Text

image

提示动画

image

在UI_Base里做了一个通用播放对应UI动画名称的两个接口

上面的是找到对应名称的UI动画.下面是具体播放的地方.这里的二级指针可能有点绕.但是这里函数返回的是一个指针.声明的二级指针前面再加一个*的话相当于解.也就是返回二级指针的解开一级也就是一级指针.一级指针就是要返回的普通指针

image

最后注意一点.做测试的时候保证所有服务器包括数据库全部打开.不然测试的时候看不到效果

分支主题 14

from blog.

WangShuXian6 avatar WangShuXian6 commented on June 5, 2024

Week3 笔记

from blog.

WangShuXian6 avatar WangShuXian6 commented on June 5, 2024

week4 笔记

from blog.

WangShuXian6 avatar WangShuXian6 commented on June 5, 2024

1 架构分布式服务器

01A_01_安装UE5源码版本

https://docs.unrealengine.com/5.3/zh-CN/downloading-unreal-engine-source-code/
https://github.com/EpicGames/UnrealEngine

运行 Setup.bat 下载依赖
21070.3 MiB
image

运行 GenerateProjectFiles.bat 回车 来设置项目文件

所有项目文件都是中间文件([虚幻引擎根目录]\Engine\Intermediate\ProjectFiles)。每次同步新构建时都必须生成项目文件,以确保它们是最新文件。如果你删除了Intermediate文件夹,必须使用 GenerateProjectFiles 批处理文件来重新生成项目文件。

安装 visual studio community https://visualstudio.microsoft.com/zh-hans/vs/ 仅用以编译虚幻引擎为二进制

从源代码构建虚幻引擎

https://docs.unrealengine.com/5.3/zh-CN/building-unreal-engine-from-source/

双击 UE5.sln 将项目加载到Visual Studio。

首次编译需要安装必须组件,点击安装即可
image

将解决方案配置设置为 开发编辑器(Development Editor)。或者 DebugGame Editor
Development 性能优于debug
image

将解决方案平台设置为 Win64。

右键单击UE目标并选择 构建(Build)。
构建只需要一次,除非更新虚幻版本。
编译耗时很长很长

image

运行编辑器
将启动项目设置为 UE5。

image

右键单击 UE 项目,将鼠标悬停于 Debug 上,然后单击 启动新实例(Start New Instance)** 以启动编辑器。

image

或者,你可以按键盘上的 F5键 来启动编辑器的新实例。

恭喜!你已经从源代码编译并启动了引擎。

新建 第三人称C++游戏项目,名称:mmoarpg

去掉初学者包
image

这将启动mmoarpg项目的VS编辑器
选择 DebugGame EditorWin64 点击 本地Windows调试器 启动该虚幻项目
image
image

01A_02_VS安装小番茄 【不需要】

Visual Assist X_10.9.2440_汉化And破解VS2022

01A_03_安装UE5相关开发插件

首次编译游戏

先择 Games - mmoarpg 右键 -生成
image

引擎插件

安装路径为 虚幻引擎 - Engine - Plugins 目录

以下插件目录复制到 虚幻引擎 - Engine - Plugins
SimpleHTTP
SimpleMySQL
SimpleNetChannel
SimpleThread

刷新引擎

运行引擎跟目录下 GenerateProjectFiles.bat 重新设置引擎

刷新项目

右键 mmoarpg 项目目录 mmoarpg.uproject 文件- Geraneta Visual Studio Project files
image
image

编辑器重新打开 mmoarpg 项目代码
Engine - UE5 - Plugins 下即可发现新增的 SimpleHTTP 等插件
image

先择 Engine - UE5 右键 -生成 编译项目中引擎
先择 Games - mmoarpg 右键 -生成 编译项目

项目插件

01A_04_准备db和网关和登陆服务器启动结构

01A_05_数据库服务器架构概念

01A_06_架构db服务器全局配置

01A_07_部署远程数据库的准备工作

01A_08_手把手部署远端WP数据库

01A_09_架构数据库服务器

01A_10_分布式插件架构讲解

01A_11_架构数据库服务器读和写

01A_12_分离数据库日志

01A_13_架构网关服务器

01A_14_架构登陆服务器

01A_15_架构客户端网络驱动

from blog.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.