• Ue4 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种不同的网络角色走不同但恰到好处的代码逻辑值得学习。
  • 相关阅读:
    Win10下访问linux的ext4分区文件并拷贝
    Zsh 无法找到自己的anaconda python
    Motrix 代替迅雷下载 aria2的配置
    Bash与python混合编程
    如何在 非系统盘安装 wsl
    Python_01
    CC2541蓝牙学习——通用I/O口中断
    自定义弹窗
    使用windbg搜索命令辅助逆向杀软穿透驱动注册表操作
    IAT Hook
  • 原文地址:https://www.cnblogs.com/whitelily/p/16166467.html
Copyright © 2020-2023  润新知