ue4中在物体上加ui_UE4 物体位置同步相关源码分析浅谈
前言
- 多圖, 不想在源代碼寫注釋, 不想貼代碼塊, 看的不清楚
- 版本4.21混4.22, 區別不大
- 文章屬于舊有文章搬運, 之前在csdn上面
- 2019.10.27修改一版
物體位置信息同步, 或者說物體的移動同步, 是一個很大的坑, 從個人目前魔改UE4位置同步后, 感覺至少要考慮以下幾點
- 位置信息的數據結構
- 要減少單次網絡同步時的傳輸數據大小, 但也要包含所需要的完整的位置信息.
- 同時在降低精度的情況下減少一些數據的大小, 例如降低Location和Rotation的精度, 用更少的位數傳播
- 位置信息的同步觸發時間, 生成時間
- 指控制什么時候位置進行網絡同步, 什么時候不需要同步. 以及什么時候生成需要同步的位置信息
- 位置信息的權威端
- 以哪一端或者哪里的物體位置, 當做最新位置同步, 作為權威端
- 如果權威端只在服務器, 那很簡單.
- 如果權威端只在單一客戶端, 服務器做驗證處理, 此時邏輯也比較簡單, 客戶端發送位置到服務器, 服務器直接應用(不考慮防作弊, 防作弊的話此時權威端還是服務器, 實現會很復雜和麻煩)
- 如果權威端在多個客戶端和服務器之間切換, 嗯, 坑很深....
- 接受到位置信息之后的處理, 減少網絡傳輸的延遲頻率丟失的一些位置信息帶來的影響, 使得整個物體移動平滑, 例如游戲中的角色運動同步
- 這里面學問很深, 自行百度谷歌(找不到當初看學習的文章了)
- 判斷位置同步信息是否有意義, 丟棄掉無用的位置信息
- 對舊的信息不做處理, 主要是解決網絡的丟包, 延遲等帶來的問題
- 對不是權威端的信息不做處理, 解決一些事件調用先后順序有別, 狀態同步不及時等等的時序問題
UE4 的位置同步是一個比較常用的功能, 實現也比較簡單, 只是服務器當方向向客戶端同步物體的位置信息.
下文將深扒一下位置同步的代碼實現, 以及對一些有坑的地方進行描述.
關鍵函數和結構體信息
/** Returns the properties used for network replication */ virtual void AActor::GetLifetimeReplicatedProps( TArray< FLifetimeProperty > & OutLifetimeProps ) const// 在屬性同步前調用的一個函數, 這里生成需要同步的位置信息, 并重寫是否需要位置同步 /*** Called on the actor right before replication occurs. * Only called on Server, and for autonomous proxies if recording a Client Replay.*/ virtual void AActor::PreReplication( IRepChangedPropertyTracker & ChangedPropertyTracker )// 生成物體同步信息的函數 /** Fills ReplicatedMovement property */ virtual void GatherCurrentMovement();// 位置同步的結構體信息 /** Used for replication of our RootComponent's position and velocity */ UPROPERTY(EditDefaultsOnly, ReplicatedUsing=OnRep_ReplicatedMovement, Category=Replication, AdvancedDisplay) struct FRepMovement ReplicatedMovement;// Attach相關的結構體信息 /*** Used for replicating attachment of this actor's RootComponent to another actor.* This is filled in via GatherCurrentMovement() when the RootComponent has an AttachParent.*/ UPROPERTY(Transient, ReplicatedUsing=OnRep_AttachmentReplication) struct FRepAttachment AttachmentReplication;同步屬性相關
從最開始的地方說起, UE4中物體位置同步是靠Actor本身屬性同步實現的, 如下:
- bReplicateMovement 控制是否進行同步
- AttachmentReplication 同步Attach相關, 是一個FRepAttachment, 即Relative Position(相對位置)
可以看到這個結構體里面是一個相對位置的同步信息
- ReplicatedMovement 同步位置信息, 絕對位置
同步基礎的位置信息, 會同步物理狀態
LocationQuantizationLevel, VelocityQuantizationLevel, RotationQuantizationLevel三個值是精度, 可以控制Vector和Rotator用多少位傳輸
控制屬性同步及生成位置信息
在屬性同步前, 需要生成位置同步信息, 并修改同步條件
ReplicatedMovement同步條件 bReplicateMovement為True
AttachmentReplication同步條件 根組件存在并且根組件不同步
然后我們看一下GatherCurrentMovement函數
- 該函數在每次屬性同步前都會被調用, 以生成相應的位置信息.
- bReplicateMovement 生成 ReplicatedMovement
- RootComponent->GetAttachParent() 生成 AttachmentReplication
- 判斷是否開啟物理, 物理的同步和沒有物理的同步方式不一樣
- 開啟物理時
- 會同步位置旋轉速度和是否休眠
- 同時注意在Welded時, 不會進行物理同步(沒有接觸過)
- 沒有開啟物理的情況下
- 如果有父組件, 相對位置, 生成AttachementReplication
- 如果無, 絕對位置, 生成ReplicatedMovement
同步后的處理
這個時候的處理就比較簡單了, 在這兩個函數中將這些信息設置到本地就行了
OnRep_ReplicatedMovement
有興趣的自己扒吧
OnRep_AttachmentReplication
判斷AttachParent是否存在是Attach還是Detach
Detach就很簡單了, 直接調用DetachFromActor然后判斷是否同步位置, 如果同步, 則調用用OnRep_ReplicatedMovement, 應用絕對位置
有坑見下文
一個的問題
注意一下這段長長的注釋, 絕對是4.21版本修復的.
Attach相關的相對同步, 會造成上面說的那個問題
這個問題會導致什么呢?
Detach相關的函數同步處理時, 會調用OnRep_ReplicateMovement函數
但由于沒有開啟bReplicateMovement, ReplicatedMovement屬性為空, 是無效值
但由于數據不存在, 會讓Actor位置, 旋轉歸零.
所以, 如果版本較低的請注意了
4.19前絕對有這個bug, 那時候魔改物體同步時, 踩過這個坑
4.20 應該也沒有, 工作用的20, 最近再次碰到過這個坑
但自己電腦上只裝了15和21(其他的都卸載了), 沒有辦法(懶)驗證了
4.21版本才修復4.21版本才修復4.21版本才修復
結語
- 能用UE4最新的版本就有最新的版本, 雖然會踩很多新坑, 但比踩那些已知bug待修復的坑好的多
- 2019.10.27, 有時候踩坑踩著, 最后查到官方, 一句已知bug, 某某版本修復.... 很無語...
- UE4同步相關的處理做好, 這里位置同步的是實現感覺很簡單了
- 騙贊了, 騙評論了, 不要再一次單機啊.
- 2019.10.27, 看到這個單機.... 嗯, 沒有單機了....
總結
以上是生活随笔為你收集整理的ue4中在物体上加ui_UE4 物体位置同步相关源码分析浅谈的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php mail laravel,邮件
- 下一篇: web前端开发论文写作_外语论文文献引言