Skip to content

Commit 6bd82eb

Browse files
committed
Port physics interpolation docs from 3.6
1 parent 53ce972 commit 6bd82eb

11 files changed

+657
-0
lines changed

tutorials/physics/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ Physics
1919
collision_shapes_3d
2020
large_world_coordinates
2121
troubleshooting_physics_issues
22+
interpolation/index
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
.. _doc_2d_and_3d_physics_interpolation:
2+
3+
2D and 3D physics interpolation
4+
===============================
5+
6+
Generally 2D and 3D physics interpolation work in very similar ways. However, there
7+
are a few differences, which will be described here.
8+
9+
Global versus local interpolation
10+
---------------------------------
11+
12+
- In 3D, physics interpolation is performed *independently* on the **global
13+
transform** of each 3D instance.
14+
- In 2D by contrast, physics interpolation is performed on the **local transform**
15+
of each 2D instance.
16+
17+
This has some implications:
18+
19+
- In 3D, it is easy to turn interpolation on and off at the level of each ``Node``,
20+
via the ``physics_interpolation_mode`` property in the Inspector, which can be
21+
set to ``On``, ``Off``, or ``Inherited``.
22+
23+
.. figure:: img/physics_interpolation_mode.webp
24+
:align: center
25+
26+
- However this means that in 3D, pivots that occur in the ``SceneTree`` (due to
27+
parent child relationships) can only be interpolated **approximately** over the
28+
physics tick. In most cases this will not matter, but in some situations the
29+
interpolation can look slightly *off*.
30+
- In 2D, interpolated local transforms are passed down to children during
31+
rendering. This means that if a parent is set to ``physics_interpolation_mode``
32+
``On``, but the child is set to ``Off``, the child will still be interpolated if
33+
the parent is moving. *Only the child's local transform is uninterpolated.*
34+
Controlling the on / off behavior of 2D nodes therefore requires a little more
35+
thought and planning.
36+
- On the positive side, pivot behavior in the scene tree is perfectly preserved
37+
during interpolation in 2D, which gives super smooth behaviour.
38+
39+
reset_physics_interpolation()
40+
-----------------------------
41+
42+
Whenever objects are moved to a completely new position, and interpolation is not
43+
desired (so as to prevent a "streaking" artefact), it is the responsibility of the
44+
user to call ``reset_physics_interpolation()``.
45+
46+
The good news is that in 2D, this is automatically done for you when nodes first
47+
enter the tree. This reduces boiler plate, and reduces the effort required to get
48+
an existing project working.
49+
50+
.. note:: If you move objects *after* adding to the scene tree, you will still need
51+
to call ``reset_physics_interpolation()`` as with 3D.
52+
53+
2D Particles
54+
------------
55+
56+
Currently only ``CPUParticles2D`` are supported for physics interpolation in 2D. It
57+
is recommended to use a physics tick rate of at least 20-30 ticks per second to
58+
keep particles looking fluid.
59+
60+
``Particles2D`` (GPU particles) are not yet interpolated, so for now it is
61+
recommended to convert to ``CPUParticles2D`` (but keep a backup of your
62+
``Particles2D`` in case we get these working).
63+
64+
Other
65+
-----
66+
67+
- ``get_global_transform_interpolated()`` - this is currently only available for 3D.
68+
- ``MultiMeshes`` - these should be supported in both 2D and 3D.
69+
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
.. _doc_advanced_physics_interpolation:
2+
3+
Advanced physics interpolation
4+
==============================
5+
6+
Although the previous instructions will give satisfactory results in a lot of games,
7+
in some cases you will want to go a stage further to get the best possible results
8+
and the smoothest possible experience.
9+
10+
Exceptions to automatic physics interpolation
11+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
Even with physics interpolation active, there may be some local situations where
14+
you would benefit from disabling automatic interpolation for a
15+
:ref:`Node<class_Node>` (or branch of the :ref:`SceneTree<class_SceneTree>`), and
16+
have the finer control of performing interpolation manually.
17+
18+
This is possible using the :ref:`Node.physics_interpolation_mode<class_Node_property_physics_interpolation_mode>`
19+
property which is present in all Nodes. If you for example, turn off interpolation
20+
for a Node, the children will recursively also be affected (as they default to
21+
inheriting the parent setting). This means you can easily disable interpolation for
22+
an entire subscene.
23+
24+
The most common situation where you may want to perform your own interpolation is
25+
Cameras.
26+
27+
Cameras
28+
^^^^^^^
29+
30+
In many cases, a :ref:`Camera3D<class_Camera3D>` can use automatic interpolation
31+
just like any other node. However, for best results, especially at low physics tick
32+
rates, it is recommended that you take a manual approach to Camera interpolation.
33+
34+
This is because viewers are very sensitive to Camera movement. For instance, a
35+
Camera that realigns slightly every 1/10th of a second (at 10tps tick rate) will
36+
often be noticeable. You can get a much smoother result by moving the Camera each
37+
frame in ``_process``, and following an interpolated target manually.
38+
39+
Manual Camera interpolation
40+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
41+
42+
**Ensure the Camera is using global coordinate space**
43+
44+
The very first step when performing manual Camera interpolation is to make sure the
45+
Camera transform is specified in *global space* rather than inheriting the
46+
transform of a moving parent. This is because feedback can occur between the
47+
movement of a parent node of a Camera and the movement of the Camera Node itself,
48+
which can mess up the interpolation.
49+
50+
There are two ways of doing this:
51+
52+
1) Move the Camera so it is independent on its own branch, rather than being a child of a moving object.
53+
54+
.. image:: img/fti_camera_worldspace.webp
55+
56+
2) Call :ref:`Node3D.top_level<class_Node3D_property_top_level>` and set this to ``true``, which will make the Camera ignore the transform of its parent.
57+
58+
Typical example
59+
^^^^^^^^^^^^^^^
60+
61+
A typical example of a custom approach is to use the ``look_at`` function in the
62+
Camera every frame in ``_process()`` to look at a target node (such as the player).
63+
64+
But there is a problem. If we use the traditional ``get_global_transform()`` on a
65+
Camera "target" Node, this transform will only focus the Camera on the target *at
66+
the current physics tick*. This is *not* what we want, as the Camera will jump
67+
about on each physics tick as the target moves. Even though the Camera may be
68+
updated each frame, this does not help give smooth motion if the *target* is only
69+
changing each physics tick.
70+
71+
get_global_transform_interpolated()
72+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
73+
74+
What we really want to focus the Camera on, is not the position of the target on
75+
the physics tick, but the *interpolated* position, i.e. the position at which the
76+
target will be rendered.
77+
78+
We can do this using the :ref:`Spatial.get_global_transform_interpolated<class_Node3D_method_get_global_transform_interpolated>`
79+
function. This acts exactly like getting :ref:`Spatial.global_transform<class_Node3D_property_global_transform>`
80+
but it gives you the *interpolated* transform (during a ``_process()`` call).
81+
82+
.. important:: ``get_global_transform_interpolated()`` should only be used once or
83+
twice for special cases such as Cameras. It should **not** be used
84+
all over the place in your code (both for performance reasons, and
85+
to give correct gameplay).
86+
87+
.. note:: Aside from exceptions like the Camera, in most cases, your game logic
88+
should be in ``_physics_process()``. In game logic you should be calling
89+
``get_global_transform()`` or ``get_transform()``, which will give the
90+
current physics transform (in global or local space respectively), which
91+
is usually what you will want for gameplay code.
92+
93+
Example manual Camera script
94+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
95+
96+
Here is an example of a simple fixed Camera which follows an interpolated target:
97+
98+
.. code-block:: python
99+
100+
extends Camera
101+
102+
# Node that the camera will follow
103+
var _target
104+
105+
# We will smoothly lerp to follow the target
106+
# rather than follow exactly
107+
var _target_pos : Vector3 = Vector3()
108+
109+
func _ready() -> void:
110+
# Find the target node
111+
_target = get_node("../Player")
112+
113+
# Turn off automatic physics interpolation for the Camera,
114+
# we will be doing this manually
115+
set_physics_interpolation_mode(Node.PHYSICS_INTERPOLATION_MODE_OFF)
116+
117+
func _process(delta: float) -> void:
118+
# Find the current interpolated transform of the target
119+
var tr : Transform = _target.get_global_transform_interpolated()
120+
121+
# Provide some delayed smoothed lerping towards the target position
122+
_target_pos = lerp(_target_pos, tr.origin, min(delta, 1.0))
123+
124+
# Fixed camera position, but it will follow the target
125+
look_at(_target_pos, Vector3(0, 1, 0))
126+
127+
Mouse look
128+
^^^^^^^^^^
129+
130+
Mouse look is a very common way of controlling Cameras. But there is a problem.
131+
Unlike keyboard input which can be sampled periodically on the physics tick, mouse
132+
move events can come in continuously. The Camera will be expected to react and
133+
follow these mouse movements on the next frame, rather than waiting until the next
134+
physics tick.
135+
136+
In this situation, it can be better to disable physics interpolation for the Camera
137+
node (using :ref:`Node.physics_interpolation_mode<class_Node_property_physics_interpolation_mode>`)
138+
and directly apply the mouse input to the Camera rotation, rather than apply it in
139+
``_physics_process``.
140+
141+
Sometimes, especially with Cameras, you will want to use a combination of
142+
interpolation and non-interpolation:
143+
144+
* A first person camera may position the camera at a player location (perhaps using :ref:`Spatial.get_global_transform_interpolated<class_Node3D_method_get_global_transform_interpolated>`), but control the Camera rotation from mouse look *without* interpolation.
145+
* A third person camera may similarly determine the look at (target location) of the camera using :ref:`Spatial.get_global_transform_interpolated<class_Node3D_method_get_global_transform_interpolated>`, but position the camera using mouse look *without* interpolation.
146+
147+
There are many permutations and variations of Camera types, but it should be clear
148+
that in many cases, disabling automatic physics interpolation and handling this
149+
yourself can give a better result.
150+
151+
Disabling interpolation on other nodes
152+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
153+
154+
Although Cameras are the most common example, there are a number of cases when you
155+
may wish other nodes to control their own interpolation, or be non-interpolated.
156+
Consider for example, a player in a top view game whose rotation is controlled by
157+
mouse look. Disabling physics rotation allows the player rotation to match the
158+
mouse in real-time.
159+
160+
161+
MultiMeshes
162+
^^^^^^^^^^^
163+
164+
Although most visual Nodes follow the single Node single visual instance paradigm,
165+
MultiMeshes can control several instances from the same Node. Therefore, they have
166+
some extra functions for controlling interpolation functionality on a
167+
*per-instance* basis. You should explore these functions if you are using
168+
interpolated MultiMeshes.
169+
170+
- :ref:`MultiMesh.reset_instance_physics_interpolation<class_MultiMesh_method_reset_instance_physics_interpolation>`
171+
- :ref:`MultiMesh.set_buffer_interpolated<class_MultiMesh_method_set_buffer_interpolated>`
172+
173+
Full details are in the :ref:`MultiMesh<class_MultiMesh>` documentation.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.. _doc_physics_interpolation:
2+
3+
Physics Interpolation
4+
=====================
5+
6+
.. toctree::
7+
:maxdepth: 1
8+
:name: toc-physics-interpolation
9+
10+
physics_interpolation_quick_start_guide
11+
physics_interpolation_introduction
12+
using_physics_interpolation
13+
advanced_physics_interpolation
14+
2d_and_3d_physics_interpolation

0 commit comments

Comments
 (0)