UE代碼-CharacterMovementComponent-角色移動組件


Ue4 CharacterMovementComponent 角色移動組件

這里先簡單介紹一下3種不同的網絡角色:

AutonomousProxy(自治端):

​ 一般為客戶端,對具有其控制權的角色而言為自治端。

Authority (權威端):

​ 一般就是服務器,具有數據的決定權。

SimulatedProxy(模擬端):

​ 一般為客戶端,對不具有控制權的角色而言為模擬端。

大致講講:

​ Ue根據網絡角色不同,移動邏輯也不一樣。

​ 首先發起者是自治端。自治端輸入移動的操作,並將input信息加入Vector。需要注意的是角色並不會在此處立即移動。

​ 等到下一個tick時,自治端就會取出其輸入的信息,進行完移動矯正后再正式移動。

​ 自治端的移動並不會先等權威端移動完再動,而是在本地先移動了再說。隨后便會通知權威端進行移動。

​ 權威端移動后會進行一個與自治端的預測結果的一個對比。

​ 差距過大會通知自治端需要矯正,自治端會在收到后的下一個tick矯正。

​ 差距不大會通知自治端清除移動緩存。

​ 模擬端,則是跟着服務器數據的同步,進行模擬移動。

3種網絡角色的移動流程:

TickComponent:角色的移動從tick開始
消費輸入向量

判斷一些其他情況:
	是否vaild
	有沒有掉出世界
	是否開啟物理模擬

處理 自治端:
	自治端進行移動矯正 ClientUpdatePositionAfterServerUpdate()
	自治端移動邏輯 ControlledCharacterMove():
		Tips:RootMotion可以移動沒有控制器的角色

處理 模擬端:
	模擬端進行移動復制 SimulatedTick()

Tip:

​ 大家可能會有一個疑問,沒有權威端的移動邏輯。
​ 權威端的移動(不包括監聽服務器)並不在tick中執行,而是等待自治端調用ServerMove時才處理相關邏輯。

自治端移動邏輯 ControlledCharacterMove:

自治端在Tick中會走到這里來,主要任務是移動與發包給服務器。

通過消費的輸入向量改變角色加速度

執行移動 ReplicateMoveToServer()
	合並新舊移動 NewMove->CombineWith(PendingMove, CharacterOwner, PC, OldStartLocation);
		個人猜想,不一定對:若前后移動加速度未發生改變的話,可以合並時間,從而減少數據量。
						為何不直接用SavedMove的最后一項與之合並而用PengdingMove去合並沒有理解。
						具體細節還待深入研究。
	執行本地移動 PerformMovement()
	
	將移動加入緩存列表 ClientData->SavedMoves.Push(NewMovePtr)
	
	發送服務器 CallServerMove()
權威端移動邏輯與驗證 ServerMove(RPC函數):

自治端調用的RPC函數,權威端在這里進行移動和預測,判斷是否需要矯正。

創建/獲取預測數據 ServerData = GetPredictionData_Server_Character

將移動數據加入ServerData

權威端執行移動並記錄數據結果 MoveAutonomous()
	更新移動數據
	執行移動 PerformMovement()

矯正自治端移動或確認移動 ServerMoveHandleClientError()
	進行狀態判斷盡量節省帶寬
	權威端計算自治端端移動是否需要矯正:
		需要:
			設置矯正信息
			ServerData->PendingAdjustment.bAckGoodMove = false;
		不需要:
			ServerData->PendingAdjustment.bAckGoodMove = true;

Tips:

服務器沒有在這里通知客戶端移動結果,而是等ServerReplicateActors調用SendClientAdjustment來通知。

bAckGoodMove的值代表了預測的結果。

對預測結果進行操作 SendClientAdjustment

ServerReplicateActors中調用,會根據bAckGoodMove的值來判斷是否需要矯正。

bAckGoodMove == true;
	發送RPC函數給自治端:ClientAckGoodMove()
		"以下在自治端":
		找到SavedData對應的索引 index
		將SavedData緩存清除:ClientData->AckMove(index)

bAckGoodMove = false;
	通知自治端進行矯正:ClientAdjustPosition()
		"以下在自治端":
		Tips:這里會根據ServerData里情況的不同進行不同的通知,AdjustPosition只是其中一種
		自治端保存矯正信息ClientData,並在下一次TickComponent中等待ClientUpdatePositionAfterServerUpdate進行移動矯正
模擬端進行移動復制 SimulatedTick

在最上面的Tick中調用,處理模擬端的移動。

分類討論集中情況,播放RootMotion,不用RootMotion的,對不同的情況進行平滑處理,模擬移動等,動畫細節暫不做分析了。
執行移動函數,與自治端,權威端一樣:PerformMovement
執行本地移動 PerformMovement:

移動的具體實現,暫時不分析那么細了。

具體實現角色移動
	服務器與客戶端:變更狀態,更新變換,速度,回調委托等
	服務器:
		更新時間戳:有客戶端信息用客戶端信息更新,否則用本地時間。
收獲:
  1. 對於相似的移動,Ue4會嘗試將其合並減少數據包以減少帶寬消耗。在其他類似情景下也能考慮考慮是否能像這樣優化。
  2. 自治端並非需要等到服務器的同步在移動,可以讓自己先動再等服務器矯正以提升玩家游戲體驗。
  3. 移動矯正設置了容忍范圍,可以考慮是否可以通過修改其范圍,來提升角色移動的精確度或降低開銷。
  4. 根據3種不同的網絡角色走不同但恰到好處的代碼邏輯值得學習。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM