UE4角色Location远距离时动画抖动问题(float精度不够)解决方案

正题:关于UE4引擎当角色Location超过9999.999后,角色动画更新抖动问题的解决思路。
前提:
1.UE4引擎中距离单位是厘米(cm),也就说我们制作好1.8米的角色在UE4中为180个虚幻单位。这样做个人愚见是为了提高浮点值(float)后面的精度。
2.UE4中Location的单位是使用的FVector,FVector是由3个float组成X,Y,Z。在DX11渲染模式下使用SSE指令集进行CPU加速计算优化,使用的是__m128(float4)由4个float浮点值组成。见下图:


3.插槽Socket的更新是在CPU直接通过骨骼(bone)的矩阵直接去乘Component矩阵或者是Actor矩阵或者是Word矩阵得到的结果,所以基本不存在GPU更新CPU更新的问题。
发现问题:
角色在大世界无缝拼接的地图上移动时或者不定位置进行运行时,相机离角色模型或者插槽(Socket)绑定的模型(Mesh)很近时会发现角色或者绑定在插槽上的模型开始抖动,并且在多次测试中发现抖动幅度并不一致。
透过现象猜本质:(推测)
1. 相机离角色部位或者插槽模型很近时遮蔽大部分骨骼,occ会踢出或降低骨骼在GPU更新频率。
2. 当角色远离原点时或者相机只看到绑定点时,骨骼或者动画会LOD降低末端骨骼更新频率或者降低计算精度。
3.当角色远离原点时3个float组成的FVector精度不够。(推测时认为可能性极低,引擎应该考虑过精度问题,并且当时角色距离原点位置目测不远)
4. 写代码时获取插槽位置方式不正确,或是Mesh绑定方式不正确。(推测时认为可能性极大... 找问题先从自身出发...)
测试:用~控制台-命令行DEBUGSHOWANIMATION显示骨骼和动画信息,并且更好绑定方式和获取插槽坐标,并用多种输出方式和输出断点调试输出位置信息。
最终经过多次测试和代码调试发现当角色Location超过9999.999后因为float只能保证7位有效数据而导致精度出现问题从而骨骼更新时出现抖动问题,并且小数点前面的位数越多精度越底。
解决思路:
1. 修改float单精度浮点值为双精度浮点值。 2. 修改本地坐标或者基础虚幻距离单位。
解决方案:(支持RPC)
使用WorldOrigin世界原点偏移来解决float精度不够问题。UnrealEngine4.12版本后加入并完善了大世界无缝地图模块(WorldTravel)和编辑功能,在Levels编辑器中可以加入子关卡作为流关卡加载(LevelStraming)。可以在主关卡的世界设置里(WorldSeting)中设置启用WorldComponent并且勾选世界原点偏移WorldOrigin。
1. 在配置文件中添加 p.EnableMultiplayerWorldOriginRebasing=true
2. 当角色将要超过9999.99之前判断当前角色是否超过自己业务中设定最大偏移值。如果超过请使用voidUGameplayStatics::GetWorldOriginLocation获得当前原点坐标的世界位置(转换前的真实位置:比如之前把8800,0,0转换成了0,0,0)加上角色的当前位置再使用UGameplayStatics::SetWorldOriginLocation来设置角色的当前位置为新的世界坐标的原点,这样角色在更新动画时或者进行其他计算时会按照当前设置的位置作为原点(0,0,0)点更新或计算从而减小误差。
3. 注意这两个API的入参和返回值都是FIntVector转换时不要丢掉精度。当客户端SetWorldOriginLocation时Levels会遍历所有关卡中的Level.Actor.Component进行WorldOffset修改会比较耗时(尤其是关卡中物体很多时请诸君慎用)最好是做一个坐标管理器系统(CoordSystem)搭配多种策略来进行使用,减少使用频次。例如:当需要近距离观察角色或者插槽上挂的Mesh时更新,或者FPS游戏拿出可以开启瞄准或者开镜武器时,角色位置每当超过8888时等等。
4.世界原点偏移(WorldOrigin)在RPC模式下只会修改客户端位置,在移动同步(Movement)根骨骼位移(RootMotion)物理计算模拟(PhysicsSimulate)时在同步时会把角色当前位置和世界原点偏移位置加起来一起发到服务器。服务器接收的真实位置而不是修改世界原点后角色位置。

猜你喜欢

转载自blog.csdn.net/sukhoi27smk/article/details/80457446