-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add physics interpolation docs to 4.3
- Loading branch information
Showing
11 changed files
with
686 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,3 +19,4 @@ Physics | |
collision_shapes_3d | ||
large_world_coordinates | ||
troubleshooting_physics_issues | ||
interpolation/index |
72 changes: 72 additions & 0 deletions
72
tutorials/physics/interpolation/2d_and_3d_physics_interpolation.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
.. _doc_2d_and_3d_physics_interpolation: | ||
|
||
2D and 3D physics interpolation | ||
=============================== | ||
|
||
Generally 2D and 3D physics interpolation work in very similar ways. However, | ||
there are a few differences, which will be described here. | ||
|
||
.. note:: currently only 2D physics interpolation works in Godot. | ||
3D interpolation is expected to come in a future update. | ||
|
||
Global versus local interpolation | ||
--------------------------------- | ||
|
||
- In 3D, physics interpolation is performed *independently* on the **global | ||
transform** of each 3D instance. | ||
- In 2D by contrast, physics interpolation is performed on the **local | ||
transform** of each 2D instance. | ||
|
||
This has some implications: | ||
|
||
- In 3D, it is easy to turn interpolation on and off at the level of each | ||
``Node``, via the ``physics_interpolation_mode`` property in the Inspector, | ||
which can be set to ``On``, ``Off``, or ``Inherited``. | ||
|
||
.. figure:: img/physics_interpolation_mode.webp | ||
:align: center | ||
|
||
- However this means that in 3D, pivots that occur in the ``SceneTree`` | ||
(due to parent child relationships) can only be interpolated | ||
**approximately** over the physics tick. In most cases this will not | ||
matter, but in some situations the interpolation can look slightly *off*. | ||
- In 2D, interpolated local transforms are passed down to children during | ||
rendering. This means that if a parent is set to | ||
``physics_interpolation_mode`` ``On``, but the child is set to ``Off``, | ||
the child will still be interpolated if the parent is moving. *Only the | ||
child's local transform is uninterpolated.* Controlling the on / off | ||
behaviour of 2D nodes therefore requires a little more thought and planning. | ||
- On the positive side, pivot behaviour in the scene tree is perfectly | ||
preserved during interpolation in 2D, which gives super smooth behaviour. | ||
|
||
reset_physics_interpolation() | ||
----------------------------- | ||
|
||
Whenever objects are moved to a completely new position, and interpolation is | ||
not desired (so as to prevent a "streaking" artefact), it is the | ||
responsibility of the user to call ``reset_physics_interpolation()``. | ||
|
||
The good news is that in 2D, this is automatically done for you when nodes | ||
first enter the tree. This reduces boiler plate, and reduces the effort | ||
required to get an existing project working. | ||
|
||
.. note:: If you move objects *after* adding to the scene tree, you will still | ||
need to call ``reset_physics_interpolation()`` as with 3D. | ||
|
||
2D Particles | ||
------------ | ||
|
||
Currently only ``CPUParticles2D`` are supported for physics interpolation in | ||
2D. It is recommended to use a physics tick rate of at least 20-30 ticks per | ||
second to keep particles looking fluid. | ||
|
||
``Particles2D`` (GPU particles) are not yet interpolated, so for now it is | ||
recommended to convert to ``CPUParticles2D`` (but keep a backup of your | ||
``Particles2D`` in case we get these working). | ||
|
||
Other | ||
----- | ||
|
||
- ``get_global_transform_interpolated()`` - this is currently only available for 3D. | ||
- ``MultiMeshes`` - these should be supported in both 2D and 3D. | ||
|
185 changes: 185 additions & 0 deletions
185
tutorials/physics/interpolation/advanced_physics_interpolation.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
.. _doc_advanced_physics_interpolation: | ||
|
||
Advanced physics interpolation | ||
============================== | ||
|
||
Although the previous instructions will give satisfactory results in a lot of | ||
games, in some cases you will want to go a stage further to get the best | ||
ossible results and the smoothest possible experience. | ||
|
||
Exceptions to automatic physics interpolation | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Even with physics interpolation active, there may be some local situations | ||
where you would benefit from disabling automatic interpolation for a | ||
:ref:`Node<class_Node>` (or branch of the :ref:`SceneTree<class_SceneTree>`), | ||
and have the finer control of performing interpolation manually. | ||
|
||
This is possible using the :ref:`Node.physics_interpolation_mode<class_Node_property_physics_interpolation_mode>` | ||
property which is present in all Nodes. If you for example, turn off | ||
interpolation for a Node, the children will recursively also be affected (as | ||
they default to inheriting the parent setting). This means you can easily | ||
disable interpolation for an entire subscene. | ||
|
||
The most common situation where you may want to perform your own | ||
interpolation is Cameras. | ||
|
||
Cameras | ||
^^^^^^^ | ||
|
||
In many cases, a :ref:`Camera<class_Camera>` can use automatic interpolation | ||
just like any other node. However, for best results, especially at low | ||
physics tick rates, it is recommended that you take a manual approach to | ||
Camera interpolation. | ||
|
||
This is because viewers are very sensitive to Camera movement. For instance, | ||
a Camera that realigns slightly every 1/10th of a second (at 10tps tick rate) | ||
will often be noticeable. You can get a much smoother result by moving the | ||
Camera each frame in ``_process``, and following an interpolated target | ||
manually. | ||
|
||
Manual Camera interpolation | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
**Ensure the Camera is using global coordinate space** | ||
|
||
The very first step when performing manual Camera interpolation is to make | ||
sure the Camera transform is specified in *global space* rather than | ||
inheriting the transform of a moving parent. This is because feedback can | ||
occur between the movement of a parent node of a Camera and the movement of | ||
the Camera Node itself, which can mess up the interpolation. | ||
|
||
There are two ways of doing this: | ||
|
||
1) Move the Camera so it is independent on its own branch, rather than being | ||
a child of a moving object. | ||
|
||
.. image:: img/fti_camera_worldspace.png | ||
|
||
2) Call :ref:`Spatial.set_as_toplevel<class_Spatial_method_set_as_toplevel>` | ||
and set this to ``true``, which will make the Camera ignore the transform of | ||
its parent. | ||
|
||
Typical example | ||
^^^^^^^^^^^^^^^ | ||
|
||
A typical example of a custom approach is to use the ``look_at`` function in | ||
the Camera every frame in ``_process()`` to look at a target node (such as | ||
the player). | ||
|
||
But there is a problem. If we use the traditional ``get_global_transform()`` | ||
on a Camera "target" Node, this transform will only focus the Camera on the | ||
target *at the current physics tick*. This is *not* what we want, as the | ||
Camera will jump about on each physics tick as the target moves. Even though | ||
the Camera may be updated each frame, this does not help give smooth motion | ||
if the *target* is only changing each physics tick. | ||
|
||
get_global_transform_interpolated() | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
What we really want to focus the Camera on, is not the position of the target | ||
on the physics tick, but the *interpolated* position, i.e. the position at | ||
which the target will be rendered. | ||
|
||
We can do this using the :ref:`Spatial.get_global_transform_interpolated<class_Spatial_method_get_global_transform_interpolated>` | ||
function. This acts exactly like getting :ref:`Spatial.global_transform<class_Spatial_property_global_transform>` | ||
but it gives you the *interpolated* transform (during a ``_process()`` call). | ||
|
||
.. important:: ``get_global_transform_interpolated()`` should only be used | ||
once or twice for special cases such as Cameras. It should | ||
**not** be used all over the place in your code (both for | ||
performance reasons, and to give correct gameplay). | ||
|
||
.. note:: Aside from exceptions like the Camera, in most cases, your game | ||
logic should be in ``_physics_process()``. In game logic you should | ||
be calling ``get_global_transform()`` or ``get_transform()``, which | ||
will give the current physics transform (in global or local space | ||
respectively), which is usually what you will want for gameplay | ||
code. | ||
|
||
Example manual Camera script | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Here is an example of a simple fixed Camera which follows an interpolated | ||
target: | ||
|
||
.. code-block:: python | ||
extends Camera | ||
# Node that the camera will follow | ||
var _target | ||
# We will smoothly lerp to follow the target | ||
# rather than follow exactly | ||
var _target_pos : Vector3 = Vector3() | ||
func _ready() -> void: | ||
# Find the target node | ||
_target = get_node("../Player") | ||
# Turn off automatic physics interpolation for the Camera, | ||
# we will be doing this manually | ||
set_physics_interpolation_mode(Node.PHYSICS_INTERPOLATION_MODE_OFF) | ||
func _process(delta: float) -> void: | ||
# Find the current interpolated transform of the target | ||
var tr : Transform = _target.get_global_transform_interpolated() | ||
# Provide some delayed smoothed lerping towards the target position | ||
_target_pos = lerp(_target_pos, tr.origin, min(delta, 1.0)) | ||
# Fixed camera position, but it will follow the target | ||
look_at(_target_pos, Vector3(0, 1, 0)) | ||
Mouse look | ||
^^^^^^^^^^ | ||
|
||
Mouse look is a very common way of controlling Cameras. But there is a | ||
problem. Unlike keyboard input which can be sampled periodically on the | ||
physics tick, mouse move events can come in continuously. The Camera will | ||
be expected to react and follow these mouse movements on the next frame, | ||
rather than waiting until the next physics tick. | ||
|
||
In this situation, it can be better to disable physics interpolation for the | ||
Camera node (using :ref:`Node.physics_interpolation_mode<class_Node_property_physics_interpolation_mode>`) | ||
and directly apply the mouse input to the Camera rotation, rather than apply | ||
it in ``_physics_process``. | ||
|
||
Sometimes, especially with Cameras, you will want to use a combination of | ||
interpolation and non-interpolation: | ||
|
||
* A first person camera may position the camera at a player location (perhaps | ||
using :ref:`Spatial.get_global_transform_interpolated<class_Spatial_method_get_global_transform_interpolated>`), | ||
but control the Camera rotation from mouse look *without* interpolation. | ||
* A third person camera may similarly determine the look at (target location) | ||
of the camera using :ref:`Spatial.get_global_transform_interpolated<class_Spatial_method_get_global_transform_interpolated>`, | ||
but position the camera using mouse look *without* interpolation. | ||
|
||
There are many permutations and variations of Camera types, but it should be | ||
clear that in many cases, disabling automatic physics interpolation and | ||
handling this yourself can give a better result. | ||
|
||
Disabling interpolation on other nodes | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
Although Cameras are the most common example, there are a number of cases | ||
when you may wish other nodes to control their own interpolation, or be | ||
non-interpolated. Consider for example, a player in a top view game whose | ||
rotation is controlled by mouse look. Disabling physics rotation allows the | ||
player rotation to match the mouse in real-time. | ||
|
||
|
||
MultiMeshes | ||
^^^^^^^^^^^ | ||
|
||
Although most visual Nodes follow the single Node single visual instance | ||
paradigm, MultiMeshes can control several instances from the same Node. | ||
Therefore, they have some extra functions for controlling interpolation | ||
functionality on a *per-instance* basis. You should explore these functions | ||
if you are using interpolated MultiMeshes. | ||
|
||
- :ref:`MultiMesh.reset_instance_physics_interpolation<class_MultiMesh_method_reset_instance_physics_interpolation>` | ||
- :ref:`MultiMesh.set_as_bulk_array_interpolated<class_MultiMesh_method_set_as_bulk_array_interpolated>` | ||
|
||
Full details are in the :ref:`MultiMesh<class_MultiMesh>` documentation. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
.. _doc_physics_interpolation: | ||
|
||
Physics Interpolation | ||
===================== | ||
|
||
.. toctree:: | ||
:maxdepth: 1 | ||
:name: toc-physics-interpolation | ||
|
||
physics_interpolation_quick_start_guide | ||
physics_interpolation_introduction | ||
using_physics_interpolation | ||
advanced_physics_interpolation | ||
2d_and_3d_physics_interpolation |
Oops, something went wrong.