Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
使用物理插值
如何在 Godot 游戏中加入物理插值?有什么注意事项吗?
We have tried to make the system as easy to use as possible, and many existing games will work with few changes. That said there are some situations which require special treatment, and these will be described.
启用物理插值设置
The first step is to turn on physics interpolation in Project Settings > Physics > Common > Physics Interpolation You can now run your game.
It is likely that nothing looks hugely different, particularly if you are running physics at 60 TPS or a multiple of it. However, quite a bit more is happening behind the scenes.
小技巧
To convert an existing game to use interpolation, it is highly recommended that
you temporarily set
Project Settings > Physics > Common > Physics Tick per Second
to a low value such as 10
, which will make interpolation problems more obvious.
将(几乎)所有游戏逻辑从 _process 移到 _physics_process
The most fundamental requirement for physics interpolation (which you may be doing
already) is that you should be moving and performing game logic on your objects
within _physics_process
(which runs at a physics tick) rather than _process
(which runs on a rendered frame). This means your scripts should typically be doing
the bulk of their processing within _physics_process
, including responding to
input and AI.
Setting the transform of objects only within physics ticks allows the automatic interpolation to deal with transforms between physics ticks, and ensures the game will run the same whatever machine it is run on. As a bonus, this also reduces CPU usage if the game is rendering at high FPS, since AI logic (for example) will no longer run on every rendered frame.
备注
If you attempt to set the transform of interpolated objects outside the physics tick, the calculations for the interpolated position will be incorrect, and you will get jitter. This jitter may not be visible on your machine, but it will occur for some players. For this reason, setting the transform of interpolated objects should be avoided outside of the physics tick. Godot will attempt to produce warnings in the editor if this case is detected.
小技巧
This is only a soft rule. There are some occasions where you might want to teleport objects outside of the physics tick (for instance when starting a level, or respawning objects). Still, in general, you should be applying transforms from the physics tick.
确保所有间接移动都在物理周期中进行
Consider that in Godot, nodes can be moved not just directly in your own scripts, but also by automatic methods such as tweening, animation, and navigation. All these methods should also have their timing set to operate on the physics tick rather than each frame ("idle"), if you are using them to move objects (these methods can also be used to control properties that are not interpolated).
备注
Also consider that nodes can be moved not just by moving themselves, but also by moving parent nodes in the SceneTree. The movement of parents should therefore also only occur during physics ticks.
选择物理周期率
使用物理插值时,渲染与物理解耦,你可以根据自己的游戏选择合适的值,不再受限于用户显示器刷新率的倍数(如果达到目标 FPS,可以实现无卡顿的游戏体验)。
大致的参考:
低周期率(10-30) |
中等周期率(30-60) |
高周期率(60+) |
---|---|---|
CPU 性能更佳 |
复杂场景中物理行为良好 |
适合快速物理 |
引入一些输入延迟 |
适合第一人称游戏 |
适合赛车游戏 |
简单物理行为 |
备注
You can always change the tick rate as you develop, it is as simple as changing the project setting.
传送对象时调用 reset_physics_interpolation()
Most of the time, interpolation is what you want between two physics ticks. However, there is one situation in which it may not be what you want. That is when you are initially placing objects, or moving them to a new location. Here, you don't want a smooth motion between where the object was (e.g. the origin) and the initial position - you want an instantaneous move.
The solution to this is to call the Node.reset_physics_interpolation function. What this function does under the hood is set the internally stored previous transform of the object to be equal to the current transform. This ensures that when interpolating between these two equal transforms, there will be no movement.
Even if you forget to call this, it will usually not be a problem in most situations (especially at high tick rates). This is something you can easily leave to the polishing phase of your game. The worst that will happen is seeing a streaking motion for a frame or so when you move them - you will know when you need it!
实际上有两种使用 reset_physics_interpolation()
的方法:
立定起步(例如玩家)
设置初始变换
调用
reset_physics_interpolation()
上一个变换和当前变换相同,因此不会产生初始移动。
移动起步(例如子弹)
设置初始变换
调用
reset_physics_interpolation()
第一个运动周期后会立即设置变换
The previous transform will be the starting position, and the current transform will act as though a tick of simulation has already taken place. This will immediately start moving the object, instead of having a tick delay standing still.
重要
Make sure you set the transform and call
reset_physics_interpolation()
in the correct order as shown
above, otherwise you will see unwanted "streaking".
测试和调试贴士
Even if you intend to run physics at 60 TPS, in order to thoroughly test your interpolation and get the smoothest gameplay, it is highly recommended to temporarily set the physics tick rate to a low value such as 10 TPS.
The gameplay may not work perfectly, but it should enable you to more easily see cases where you should be calling Node.reset_physics_interpolation, or where you should be using your own custom interpolation on e.g. a Camera3D. Once you have these cases fixed, you can set the physics tick rate back to the desired setting.
The other great advantage to testing at a low tick rate is you can often notice
other game systems that are synchronized to the physics tick and creating glitches
which you may want to work around. Typical examples include setting animation blend
values, which you may decide to set in _process()
and interpolate manually.