diff --git a/tutorials/physics/index.rst b/tutorials/physics/index.rst index d220491164b0..56d8c8433be6 100644 --- a/tutorials/physics/index.rst +++ b/tutorials/physics/index.rst @@ -19,3 +19,4 @@ Physics collision_shapes_3d large_world_coordinates troubleshooting_physics_issues + interpolation/index diff --git a/tutorials/physics/interpolation/2d_and_3d_physics_interpolation.rst b/tutorials/physics/interpolation/2d_and_3d_physics_interpolation.rst new file mode 100644 index 000000000000..68c343d4e859 --- /dev/null +++ b/tutorials/physics/interpolation/2d_and_3d_physics_interpolation.rst @@ -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. + diff --git a/tutorials/physics/interpolation/advanced_physics_interpolation.rst b/tutorials/physics/interpolation/advanced_physics_interpolation.rst new file mode 100644 index 000000000000..be8e6ae76634 --- /dev/null +++ b/tutorials/physics/interpolation/advanced_physics_interpolation.rst @@ -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` (or branch of the :ref:`SceneTree`), +and have the finer control of performing interpolation manually. + +This is possible using the :ref:`Node.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` 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` +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` +function. This acts exactly like getting :ref:`Spatial.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`) +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`), + 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`, + 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` +- :ref:`MultiMesh.set_as_bulk_array_interpolated` + +Full details are in the :ref:`MultiMesh` documentation. diff --git a/tutorials/physics/interpolation/img/fti_camera_worldspace.png b/tutorials/physics/interpolation/img/fti_camera_worldspace.png new file mode 100644 index 000000000000..7cacf8780d71 Binary files /dev/null and b/tutorials/physics/interpolation/img/fti_camera_worldspace.png differ diff --git a/tutorials/physics/interpolation/img/fti_graph_fixed_ticks.png b/tutorials/physics/interpolation/img/fti_graph_fixed_ticks.png new file mode 100644 index 000000000000..8d484f962b70 Binary files /dev/null and b/tutorials/physics/interpolation/img/fti_graph_fixed_ticks.png differ diff --git a/tutorials/physics/interpolation/img/fti_graph_interpolated.png b/tutorials/physics/interpolation/img/fti_graph_interpolated.png new file mode 100644 index 000000000000..5b99ad8663c6 Binary files /dev/null and b/tutorials/physics/interpolation/img/fti_graph_interpolated.png differ diff --git a/tutorials/physics/interpolation/img/physics_interpolation_mode.webp b/tutorials/physics/interpolation/img/physics_interpolation_mode.webp new file mode 100644 index 000000000000..c14c04877d8b Binary files /dev/null and b/tutorials/physics/interpolation/img/physics_interpolation_mode.webp differ diff --git a/tutorials/physics/interpolation/index.rst b/tutorials/physics/interpolation/index.rst new file mode 100644 index 000000000000..92ce6c244840 --- /dev/null +++ b/tutorials/physics/interpolation/index.rst @@ -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 diff --git a/tutorials/physics/interpolation/physics_interpolation_introduction.rst b/tutorials/physics/interpolation/physics_interpolation_introduction.rst new file mode 100644 index 000000000000..b4a8b6e3b5d4 --- /dev/null +++ b/tutorials/physics/interpolation/physics_interpolation_introduction.rst @@ -0,0 +1,241 @@ +.. _doc_physics_interpolation_introduction: + +Introduction +============ + +Physics ticks and rendered frames +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One key concept to understand in Godot is the distinction between physics +ticks (sometimes referred to as iterations or physics frames), and rendered +frames. The physics proceeds at a fixed tick rate +(set in :ref:`ProjectSettings.physics/common/physics_fps`), +which defaults to 60 ticks per second. + +However, the engine does not necessarily **render** at the same rate. +Although many monitors refresh at 60 Hz (cycles per second), many refresh at +completely different frequencies (e.g. 75 Hz, 144 Hz, 240 Hz or more). Even +though a monitor may be able to show a new frame e.g. 60 times a second, +there is no guarantee that the CPU and GPU will be able to *supply* frames at +this rate. For instance, when running with V-Sync, the computer may be too +slow for 60 and only reach the deadlines for 30 FPS, in which case the frames +you see will change at 30 FPS (resulting in stuttering). + +But there is a problem here. What happens if the physics ticks do not +coincide with frames? What happens if the physics tick rate is out of phase +with the frame rate? Or worse, what happens if the physics tick rate is +*lower* than the rendered frame rate? + +This problem is easier to understand if we consider an extreme scenario. If +you set the physics tick rate to 10 ticks per second, in a simple game with +a rendered frame rate of 60 FPS. If we plot a graph of the positions of an +object against the rendered frames, you can see that the positions will +appear to "jump" every 1/10th of a second, rather than giving a smooth +motion. When the physics calculates a new position for a new object, it is +not rendered in this position for just one frame, but for 6 frames. + +.. image:: img/fti_graph_fixed_ticks.png + +This jump can be seen in other combinations of tick / frame rate as glitches, +or jitter, caused by this staircasing effect due to the discrepancy between +physics tick time and rendered frame time. + +What can we do about frames and ticks being out of sync? +-------------------------------------------------------- + +Lock the tick / frame rate together? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The most obvious solution is to get rid of the problem, by ensuring there is +a physics tick that coincides with every frame. This used to be the approach +on old consoles and fixed hardware computers. If you know that every player +will be using the same hardware, you can ensure it is fast enough to +calculate ticks and frames at e.g. 50 FPS, and you will be sure it will work +great for everybody. + +However, modern games are often no longer made for fixed hardware. You will +often be planning to release on desktop computers, mobiles and more, all of +which have huge variations in performance, as well as different monitor +refresh rates. We need to come up with a better way of dealing with the +problem. + +Adapt the tick rate? +^^^^^^^^^^^^^^^^^^^^ + +Instead of designing the game at a fixed physics tick rate, we could allow +the tick rate to scale according to the end users hardware. We could for +example use a fixed tick rate that works for that hardware, or even vary +the duration of each physics tick to match a particular frame duration. + +This works, but there is a problem. Physics (*and game logic*, which is often +also run in the ``_physics_process``) work best and most consistently when +run at a **fixed**, predetermined tick rate. If you attempt to run a racing +game physics that has been designed for 60 TPS (ticks per second) at e.g. 10 +TPS, the physics will behave completely differently. Controls may be less +responsive, collisions / trajectories can be completely different. You may +test your game thoroughly at 60 TPS, then find it breaks on end users +machines when it runs at a different tick rate. + +This can make quality assurance difficult with hard to reproduce bugs, +especially in AAA games where problems of this sort can be very costly. This +can also be problematic for multiplayer games for competitive integrity, as +running the game at certain tick rates may be more advantageous than others. + +Lock the tick rate, but use interpolation to smooth frames in between physics ticks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This has become one of the most popular approaches to dealing with the +problem. It is supported by Godot 3.5 and later in 3D (although it is +optional and disabled by default). + +We have established that the most desirable physics/game logic arrangement +for consistency and predictability is a physics tick rate that is fixed at +design-time. The problem is the discrepancy between the physics position +recorded, and where we "want" a physics object to be shown on a frame to give +smooth motion. + +The answer turns out to be simple, but can be a little hard to get your head +around at first. + +Instead of keeping track of just the current position of a physics object in +the engine, we keep track of *both the current position of the object, and +the previous position* on the previous physics tick. + +Why do we need the previous position *(in fact the entire transform, +including rotation and scaling)*? By using a little math magic, we can use +**interpolation** to calculate what the transform of the object would be +between those two points, in our ideal world of smooth continuous movement. + +.. image:: img/fti_graph_interpolated.png + +Linear interpolation +^^^^^^^^^^^^^^^^^^^^ + +The simplest way to achieve this is linear interpolation, or lerping, which +you may have used before. + +Let us consider only the position, and a situation where we know that the +previous physics tick X coordinate was 10 units, and the current physics tick +X coordinate is 30 units. + +.. note:: Although the maths is explained here, you do not have to worry + about the details, as this step will be performed for you. Under + the hood, Godot may use more complex forms of interpolation, but + linear interpolation is the easiest in terms of explanation. + +The physics interpolation fraction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If our physics ticks are happening 10 times per second (for this example), +what happens if our rendered frame takes place at time 0.12 seconds? We can +do some math to figure out where the object would be to obtain a smooth +motion between the two ticks. + +First of all, we have to calculate how far through the physics tick we want +the object to be. If the last physics tick took place at 0.1 seconds, we are +0.02 seconds *(0.12 - 0.1)* through a tick that we know will take 0.1 seconds +(10 ticks per second). The fraction through the tick is thus: + +.. code-block:: python + + fraction = 0.02 / 0.10 + fraction = 0.2 + +This is called the **physics interpolation fraction**, and is handily +calculated for you by Godot. It can be retrieved on any frame by calling +:ref:`Engine.get_physics_interpolation_fraction`. + +Calculating the interpolated position +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Once we have the interpolation fraction, we can insert it into a standard +linear interpolation equation. The X coordinate would thus be: + +.. code-block:: python + + x_interpolated = x_prev + ((x_curr - x_prev) * 0.2) + +So substituting our ``x_prev`` as 10, and ``x_curr`` as 30: + +.. code-block:: python + + x_interpolated = 10 + ((30 - 10) * 0.2) + x_interpolated = 10 + 4 + x_interpolated = 14 + +Let's break that down: + +- We know the X starts from the coordinate on the previous tick (``x_prev``) + which is 10 units. +- We know that after the full tick, the difference between the current tick + and the previous tick will have been added (``x_curr - x_prev``) (which is + 20 units). +- The only thing we need to vary is the proportion of this difference we add, + according to how far we are through the physics tick. + +.. note:: Although this example interpolates the position, the same thing can + be done with the rotation and scale of objects. It is not necessary to + know the details as Godot will do all this for you. + +Smoothed transformations between physics ticks? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Putting all this together shows that it should be possible to have a nice +smooth estimation of the transform of objects between the current and +previous physics tick. + +But wait, you may have noticed something. If we are interpolating between the +current and previous ticks, we are not estimating the position of the object +*now*, we are estimating the position of the object in the past. To be exact, +we are estimating the position of the object *between 1 and 2 ticks* into the +past. + +In the past +^^^^^^^^^^^ + +What does this mean? This scheme does work, but it does mean we are +effectively introducing a delay between what we see on the screen, and where +the objects *should* be. + +In practice, most people won't notice this delay, or rather, it is typically +not *objectionable*. There are already significant delays involved in games, +we just don't typically notice them. The most significant effect is there can +be a slight delay to input, which can be a factor in fast twitch games. In +some of these fast input situations, you may wish to turn off physics +interpolation and use a different scheme, or use a high tick rate, which +mitigates these delays. + +Why look into the past? Why not predict the future? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is an alternative to this scheme, which is: instead of interpolating +between the previous and current tick, we use maths to *extrapolate* into the +future. We try to predict where the object *will be*, rather than show it +where it was. This can be done and may be offered as an option in future, but +there are some significant downsides: + +- The prediction may not be correct, especially when an object collides with + another object during the physics tick. +- Where a prediction was incorrect, the object may extrapolate into an + "impossible" position, like inside a wall. +- Providing the movement speed is slow, these incorrect predictions may not + be too much of a problem. +- When a prediction was incorrect, the object may have to jump or snap back + onto the corrected path. This can be visually jarring. + +Fixed timestep interpolation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In Godot this whole system is referred to as physics interpolation, but you +may also hear it referred to as **"fixed timestep interpolation"**, as it is +interpolating between objects moved with a fixed timestep (physics ticks per +second). In some ways the second term is more accurate, because it can also +be used to interpolate objects that are not driven by physics. + +.. tip:: Although physics interpolation is usually a good choice, there are + exceptions where you may choose not to use Godot's built-in physics + interpolation (or use it in a limited fashion). An example category + is internet multiplayer games. Multiplayer games often receive tick + or timing based information from other players or a server and these + may not coincide with local physics ticks, so a custom interpolation + technique can often be a better fit. diff --git a/tutorials/physics/interpolation/physics_interpolation_quick_start_guide.rst b/tutorials/physics/interpolation/physics_interpolation_quick_start_guide.rst new file mode 100644 index 000000000000..9c93ec501abe --- /dev/null +++ b/tutorials/physics/interpolation/physics_interpolation_quick_start_guide.rst @@ -0,0 +1,15 @@ +.. _doc_physics_interpolation_quick_start_guide: + +Quick start guide +================= + +- Turn on physics interpolation: :ref:`ProjectSettings.physics/common/physics_interpolation` +- Make sure you move objects and run your game logic in + ``_physics_process()`` rather than ``_process()``. This includes moving + objects directly *and indirectly* (by e.g. moving a parent, or using + another mechanism to automatically move nodes). +- Be sure to call :ref:`Node.reset_physics_interpolation` + on nodes *after* you first position or teleport them, to prevent + "streaking" +- Temporarily try setting :ref:`ProjectSettings.physics/common/physics_fps` + to 10 to see the difference with and without interpolation. diff --git a/tutorials/physics/interpolation/using_physics_interpolation.rst b/tutorials/physics/interpolation/using_physics_interpolation.rst new file mode 100644 index 000000000000..e7e7932b4f91 --- /dev/null +++ b/tutorials/physics/interpolation/using_physics_interpolation.rst @@ -0,0 +1,158 @@ +.. _doc_using_physics_interpolation: + +Using physics interpolation +=========================== +How do we incorporate physics interpolation into a Godot game? Are there any +caveats? + +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. + +Turn on the physics interpolation setting +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The first step is to turn on physics interpolation in :ref:`ProjectSettings.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. + +.. tip:: + + To convert an existing game to use interpolation, it is highly + recommended that you temporarily set :ref:`ProjectSettings.physics/common/physics_fps` + to a low value such as 10, which will make interpolation problems more + obvious. + +Move (almost) all game logic from _process to _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. + +.. note:: 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. + +.. tip:: 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. + + +Ensure that all indirect movement happens during physics ticks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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*). + +.. note:: Also consider that nodes can be moved not just by moving + themselves, but also by moving parent nodes in the :ref:`SceneTree`. + The movement of parents should therefore also only occur during + physics ticks. + +Choose a physics tick rate +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When using physics interpolation, the rendering is decoupled from physics, +and you can choose any value that makes sense for your game. You are no +longer limited to values that are multiples of the user's monitor refresh +rate (for stutter-free gameplay if the target FPS is reached). + +As a rough guide: + +.. csv-table:: + :header: "Low tick rates (10-30)", "Medium tick rates (30-60)", "High tick rates (60+)" + :widths: 20, 20, 20 + + "Better CPU performance","Good physics behaviour in complex scenes","Good with fast physics" + "Add some delay to input","Good for first person games","Good for racing games" + "Simple physics behaviour" + +.. note:: You can always change the tick rate as you develop, it is as simple + as changing the project setting. + +Call reset_physics_interpolation() when teleporting objects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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 :ref:`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! + +There are actually two ways to use ``reset_physics_interpolation()``: + +*Standing start (e.g. player)* + +1) Set the initial transform +2) Call ``reset_physics_interpolation()`` + +The previous and current transforms will be identical, resulting in no +initial movement. + +*Moving start (e.g. bullet)* + +1) Set the initial transform +2) Call ``reset_physics_interpolation()`` +3) Immediately set the transform expected after the first tick of motion + +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. + +.. important:: Make sure you set the transform and call + ``reset_physics_interpolation()`` in the correct order as + shown above, otherwise you will see unwanted "streaking". + +Testing and debugging tips +-------------------------- + +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 :ref:`Node.reset_physics_interpolation`, +or where you should be using your own custom interpolation on e.g. a :ref:`Camera`. +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.