UE5 c++筆記 01. 使用C++進(jìn)行LAN連接筆記
//作用:創(chuàng)建一個(gè)新的游戲大廳,并且成為主機(jī)
void AMPTestingCharacter::OpenLobby()
{
//創(chuàng)建一個(gè)UWorld類型的指針
UWorld* World = GetWorld();
//GetWorld()作用:獲取當(dāng)前對(duì)象所在的World。若World不存在,將返回NULL
//這個(gè)World是指當(dāng)前游戲所在的世界。
if (World)
{
//調(diào)用ServerTravel
// ServerTraval 是一個(gè)服務(wù)器函數(shù)。
// serverTravel函數(shù)的作用:將玩家從一個(gè)虛擬世界(當(dāng)前關(guān)卡)傳到另一個(gè)虛擬世界(另一個(gè)關(guān)卡或子關(guān)卡)
//SeverTravel傳參:
//CONST FString MapName:關(guān)卡地圖地址 ,填入關(guān)卡地圖URL地址
//bool bAbsolute :是否將MapName設(shè)為絕對(duì)路徑,默認(rèn)false,表示為相對(duì)路徑。True則是絕對(duì)路徑
//SpecificPlayer:只想特定玩家控制器對(duì)象的指針。如果指定了此參數(shù),則只有這個(gè)玩家被傳送到新的虛擬世界,若未指定,則所有人都會(huì)被傳到新世界
FString lobbyAddress = "/GAME/ThirdPerson/Maps/Lobby?listen";
//地址處理:截止至CONTENT前的地址,都可以用/GAME/來代替
//.文件類型不用處理,需要改成“?Listen". 這樣會(huì)打開lobby關(guān)卡,并且使該關(guān)卡作為listen server
//?listen 用來告訴服務(wù)器創(chuàng)建一個(gè)新的游戲繪畫,并將該玩家設(shè)置為主機(jī)(服務(wù)器)。這意味著其他玩家可以加入該游戲,并且該玩家可以控制開始或結(jié)束的游戲
//?listen通常用于單人游戲或創(chuàng)建主機(jī)托管的多人游戲
World->ServerTravel(lobbyAddress);
//補(bǔ)充:Fstrign
//在UE5中,F(xiàn)String是一個(gè)字符串類型,它是一個(gè)可變大小的Unicode字符串,它提供了許多方便的方法來處理字符串
//FString 還支持字符串格式化,可以使用一些占位符,將變量嵌入到字符中。
//FString是一個(gè)非常重要的類型,用來處理大量的文本和消息
}
}
//連接至目標(biāo)服務(wù)器方法1
傳入值:IP地址
void AMPTestingCharacter::CallOpenLevel(const FString& Address)
{
//OpenLevel是一個(gè)游戲開發(fā)函數(shù)
//OpenLevel的作用:在當(dāng)前游戲世界,打開一個(gè)新的關(guān)卡
//Openlevel傳參:
//UObject* WorldContextObject :當(dāng)前上下文的UObject對(duì)象指針,通常情況下,這里傳遞的是當(dāng)前運(yùn)行游戲的GameMode或PlayerController對(duì)象
//FName levelName:要打開的關(guān)卡名稱,可以使用FName類型或字符串字面量傳遞
//bool bAbsolute:表示是否根據(jù)絕對(duì)路徑來加載關(guān)卡。默認(rèn)為False:按照相對(duì)路徑加載
//FString Options:一個(gè)可選的字符串參數(shù),用來指定加載關(guān)卡時(shí)的一些額外選項(xiàng),例如GameInstace類型,難度級(jí)別等等等等
//為什么參數(shù)是 const FString& Address 卻可以為FNname LevelName賦值?
//因?yàn)镕Stirng和FName之間存在隱式轉(zhuǎn)換。
//在本例中,由于FString 類型可以轉(zhuǎn)換為 const char*類型,而FName類型可以從const char*類型構(gòu)造出來,因此在調(diào)用OpenLevel時(shí),會(huì)將FSring類型的參數(shù)轉(zhuǎn)化為FName型的參數(shù)
//具體來說,在這段代碼中共進(jìn)行了以下的轉(zhuǎn)換
//1. 使用Address表示獲取FString類型參數(shù)Adddress底層C字符串指針類型(const char類型)
//2. 通過FNanme構(gòu)造函數(shù),將其轉(zhuǎn)換為了FName類型
//3. 將其傳給OpenLevel函數(shù)
//通過this,在當(dāng)前世界中,打開對(duì)應(yīng)路徑的關(guān)卡地圖
//這里的Address是IP地址
//值得注意的是:官方給出的第二個(gè)值,應(yīng)該是給的關(guān)卡地址,意思是:打開一個(gè)新的關(guān)卡
//下面進(jìn)行測(cè)試:
//問題:為什么我不能直接聲明一個(gè)FString 類型的newwAddress,來匹配LevelName?
//回答:因?yàn)榧词笷String類型可以隱式的轉(zhuǎn)換為 const char*,也不能直接當(dāng)做OpenLevel的參數(shù)傳遞,需要轉(zhuǎn)換后使用
//可以調(diào)用FName構(gòu)造函數(shù),將FString類型的字符串作為參數(shù)傳遞給FName構(gòu)造函數(shù),得到一個(gè)FName對(duì)象 Fname 新對(duì)象(*FString對(duì)象)
//測(cè)試內(nèi)容:將一個(gè)新地圖的地址給到LevelName
//FString LevelName = "/Game/ThirdPerson/Maps/Map_test01";
//UGameplayStatics::OpenLevel(this, FName(*LevelName), true);
//測(cè)試完畢,當(dāng)LevelName是一個(gè)關(guān)卡的路徑時(shí),會(huì)打開對(duì)應(yīng)的關(guān)卡地圖
UGameplayStatics::OpenLevel(this, *Address);
//當(dāng)一個(gè)LevelName是一串IP時(shí),會(huì)連接到該IP
//補(bǔ)充 this
//在C++中,this是一個(gè)指向當(dāng)前對(duì)象的指針
//當(dāng)前對(duì)象:可以理解為,調(diào)用這個(gè)類的函數(shù)的類的對(duì)象
//補(bǔ)充:Fname
//在UE5.1中,F(xiàn)Name是一個(gè)用于儲(chǔ)存名稱的結(jié)構(gòu)體。
//它通過使用哈希表優(yōu)化字符串的查找速度。它通常用于將字符串作為鍵來訪問哈希表中的值,以便在內(nèi)存中高效的儲(chǔ)存大量名稱。
//在代碼中,使用FName而不是字符串,可以提高性能和效率
}
//連接至目標(biāo)服務(wù)器方法2
//傳入值:IP地址
void AMPTestingCharacter::CallClientTravel(const FString& Address)
{
//檢測(cè)是否存在玩家控制器
APlayerController* PlayerController= GetGameInstance()->GetFirstLocalPlayerController();
//APlayerController:代表玩家控制器的類,繼承自AController類,并添加了管理玩家輸入、處理網(wǎng)絡(luò)同步??刂埔晥D聲音等功能
//每個(gè)玩家在游戲中,都擁有一個(gè)對(duì)應(yīng)的玩家控制器實(shí)例。
//玩家控制器與玩家角色一起協(xié)同工作,接受玩家輸入,并將其傳遞給游戲世界,來影響游戲的狀態(tài)行為
//玩家控制器還負(fù)責(zé)處理玩家離開游戲、游戲結(jié)束、進(jìn)行網(wǎng)絡(luò)同步等操作
//GetGameInstance():用于獲取當(dāng)前正在運(yùn)行的游戲?qū)嵗?/p>
// 返回值:與當(dāng)前世界關(guān)聯(lián)的游戲?qū)嵗闹羔?/p>
// 如果當(dāng)前場(chǎng)景沒有附加到任何游戲?qū)嵗?,則該函數(shù)將返回空值
// 導(dǎo)致該指針返回空值的幾種情況:
// 1. 當(dāng)前場(chǎng)景中不存在游戲?qū)嵗?/p>
// 如果游戲尚未初始化或已經(jīng)結(jié)束,則可能沒有游戲?qū)嵗嬖?/p>
// 2. 調(diào)用該函數(shù)的對(duì)象不是控制器或游戲?qū)嵗?/p>
// GetGameInstance()函數(shù)與控制器或游戲?qū)嵗嗷リP(guān)聯(lián)
// 3. 游戲?qū)嵗呀?jīng)被銷毀
// 在某些情況下,流入切換關(guān)卡、退出游戲時(shí),游戲?qū)嵗赡軙?huì)被銷毀。
//當(dāng)前游戲?qū)嵗–urrent Game Instance)是一個(gè)在整個(gè)游戲生命中存在的單例對(duì)象,它負(fù)責(zé)管理游戲?qū)嵗嚓P(guān)的一些操作和數(shù)據(jù)。
//每個(gè)項(xiàng)目只有一個(gè)游戲?qū)嵗?,并且,它存?chǔ)在引擎中
//游戲?qū)嵗ǔS糜诖鎯?chǔ)全局游戲狀態(tài)和玩家數(shù)據(jù),例如玩家分?jǐn)?shù)、關(guān)卡列表、游戲設(shè)置德國(guó)
//可以通過在游戲?qū)嵗愔卸x這些變量和函數(shù),并且從任何繼承自UObject的藍(lán)圖或C++中訪問它們
//除了存儲(chǔ)全局的游戲狀態(tài)之外,游戲?qū)嵗€管理引擎級(jí)別的事件,例如啟動(dòng)游戲的初始化、處理游戲暫停/回復(fù)以及程序退出的清理工作等
//游戲?qū)嵗膭?chuàng)建順序
//1. 在游戲開始時(shí),引擎自動(dòng)創(chuàng)建一個(gè)GameMode對(duì)象,并用它來管理游戲。
// GameMode負(fù)責(zé)初始化游戲世界、處理玩家輸入和協(xié)調(diào)系統(tǒng),確定了默認(rèn)的Pawn類和PlayerController類,這些類用于表示玩家角色并處理他們的輸入
//2.在GameMode 對(duì)象創(chuàng)建后,引擎會(huì)使用它創(chuàng)建GameState對(duì)象
//? ?GameState對(duì)象與GameMode對(duì)象存在一對(duì)一關(guān)系,用來儲(chǔ)存有關(guān)的游戲狀態(tài)
//3. 創(chuàng)建PlayerState對(duì)象,改對(duì)象代表單個(gè)玩家并跟蹤其狀態(tài)
//4. 當(dāng)玩家啟動(dòng)游戲時(shí),會(huì)實(shí)時(shí)的創(chuàng)建一個(gè)LocalPlayer對(duì)象,該對(duì)象代表本地玩家。
//5. 創(chuàng)建PlayerController對(duì)象,處理玩家輸入以及相應(yīng)游戲事件
// PlayerController與PlayerState之間,存在一對(duì)一的關(guān)系
//6. 創(chuàng)建Pawn對(duì)象,改對(duì)象用于表示玩家角色
//? ?Pawn對(duì)象與PlayerController對(duì)象之間存在一對(duì)一的關(guān)系
//游戲?qū)嵗?GameInstance對(duì)象是如何被創(chuàng)建的?
//當(dāng)打開一個(gè)UE項(xiàng)目并且開始游戲運(yùn)行時(shí),UE會(huì)自動(dòng)創(chuàng)建一個(gè)GameInstance對(duì)象,并將其作為第一個(gè)對(duì)象加載。
//GetFirstLocalPlayerController():獲取與游戲?qū)嵗P(guān)聯(lián)的第一個(gè)本地玩家控制器(Local Player Controller)的指針。
//如何定義第一個(gè)?
//在一個(gè)游戲?qū)嵗校梢杂卸鄠€(gè)本地玩家控制器。其中,“第一個(gè)”指的是與游戲?qū)嵗P(guān)聯(lián)的序號(hào) 最小 的 本地玩家控制器。
//當(dāng)玩家進(jìn)入游戲后,系統(tǒng)為其創(chuàng)建一個(gè)本地玩家的控制器,如果有多個(gè)玩家加入游戲,則會(huì)為每個(gè)玩家創(chuàng)建一個(gè)本地玩家控制器。
//這些控制器不存在固定的先后順序,因此,在獲取第一個(gè)本地玩家控制器時(shí),引擎會(huì)返回序號(hào)最小的本地玩家控制器
//需要注意到是:不同平臺(tái)或不同設(shè)置可能導(dǎo)致本地玩家控制器的創(chuàng)建順序發(fā)生邊緣化,因此,不能假設(shè)序號(hào)最小的本地玩家控制器始終與某個(gè)特定玩家關(guān)聯(lián)
if (PlayerController)//判定當(dāng)前玩家控制器是否存在,容錯(cuò)
{
PlayerController->ClientTravel(Address,ETravelType::TRAVEL_Absolute);
//ClintTravel:PlayerController類中的一個(gè)成員函數(shù),用于讓客戶端連接到指定地址
//參數(shù):
// 1.const Fstring& URL:要連接的目標(biāo)地址,這個(gè)地址可以是任意有效的URL,比如,一個(gè)IP地址,或者是一個(gè)文本路徑
// 2.ETravelType TravelType:連接類型,包括以下枚舉值
// ? TRAVEL_Absolute:絕對(duì)地址
//? ? TRAVEL_Relative:相對(duì)地址
//? ? TRAVEL_Partial:部分地址(通常是相同關(guān)卡中的某個(gè)位置)
//? ? TRAVEL_Preload:預(yù)加載地圖以后使用
// 3.bSeamless:是否無縫過渡到新地圖
// 4.MapPackageGuid:新地圖的package GUID(如果不為None)
//可以使用ClientTravle()函數(shù)來實(shí)現(xiàn)多種功能,比如:
//· 切換到另一個(gè)關(guān)卡or地圖
//· 加入其它游戲服務(wù)器
//· 打開一個(gè)網(wǎng)頁或視頻連接
//· 連接到自定義網(wǎng)絡(luò)服務(wù)器
//需要注意的是:ClientTravel()僅適用于客戶端,不能在服務(wù)器調(diào)用此函數(shù)
}
}