Unity和Unreal中均用32位float存储坐标,当坐标超1e5时精度误差显著:1e6处最小间隔0.0625,1e7处升至0.5,导致低速移动被舍入抹除而卡住。

float 在 Unity 和 Unreal 中的坐标存储实际表现
Unity 默认用 float 存储 Vector3 的 x/y/z,Unreal 的 FVector 同样基于 float。这不是“偷懒”,而是权衡:GPU 渲染管线、物理引擎缓存对齐、内存带宽都围绕 32 位设计。一旦换成 double,Transform 组件大小翻倍,Physics.Raycast 调用开销上升 30% 以上,且多数显卡不支持双精度着色器运算。
当坐标值超过 1e5 时,float 的误差已经不可忽略
实测显示,在 x = 1000000.0f 位置,相邻可表示的 float 值间隔为 0.0625;到 1e7 时跳到 0.5。这意味着:
- 移动速度低于 0.05 单位/帧的对象可能“卡住”——坐标更新被舍入抹掉
if (Vector3.Distance(a, b) 这类判断在远距离下会失效,因为距离计算本身已失真- 碰撞检测中法线方向微小偏差会被放大,导致角色穿墙或悬浮
不用 double,也能缓解 float 坐标漂移的三个实操点
核心思路是“局部化”:把大世界拆成多个以原点为中心的子空间,每个子空间内保持 float 高精度。
- 在相机附近动态重置世界原点(如 Unity 的
transform.position -= offset),所有物体相对坐标重算,避免全局坐标持续增长 - 做空间分区(Chunk / Sector),每个区块有自己的局部坐标系,跨区通信时只传索引+局部偏移,不传绝对
float坐标 - 对关键逻辑(如射线检测、UI 锁定)单独使用
double计算中间值,但最终仍转回float写入Transform,避免破坏引擎内部假设
别信“换 double 就万事大吉”的直觉
IEEE 754 的 double 确实有 ~15 位有效数字,但在游戏运行时它带来更隐蔽的问题:
- Unity 不支持
double类型的Transform或Rigidbody,硬改会导致 Physics 系统崩溃或行为异常 - 着色器里
double基本不可用,worldPos传入后立刻降级为float,前端精度白费 - 哪怕你在 C# 层用
double算出完美坐标,调用transform.position = new Vector3((float)x, (float)y, (float)z)这一刻就又回到float精度陷阱
真正要盯住的不是数据类型,而是坐标更新链路上每一处隐式截断——从传感器输入、插值计算、到最终写入 GPU 的那一行赋值。

















