diff --git a/tutorials/physics/index.rst b/tutorials/physics/index.rst index d220491164b..56d8c8433be 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 00000000000..143cc3d3651 --- /dev/null +++ b/tutorials/physics/interpolation/2d_and_3d_physics_interpolation.rst @@ -0,0 +1,69 @@ +.. _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. + +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 wrong. +- 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 behavior of 2D nodes therefore requires a little more + thought and planning. +- On the positive side, pivot behavior in the scene tree is perfectly preserved + during interpolation in 2D, which gives super smooth behaviour. + +Resetting 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 00000000000..28140f00c46 --- /dev/null +++ b/tutorials/physics/interpolation/advanced_physics_interpolation.rst @@ -0,0 +1,174 @@ +.. _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 possible 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:`Camera3D` 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 +Camera3D 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 +Camera3D 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 Camera3D and the movement of the camera Node itself, +which can mess up the interpolation. + +There are two ways of doing this: + +1) Move the Camera3D so it is independent on its own branch, rather than being a child of a moving object. + +.. image:: img/fti_camera_worldspace.webp + +2) Call :ref:`Node3D.top_level` 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 +Camera3D 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 +Camera3D "target" node, this transform will only focus the Camera3D 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:: gdscript + + extends Camera3D + + # 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 Camera3D, + # 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_buffer_interpolated` + +Full details are in the :ref:`MultiMesh` documentation. diff --git a/tutorials/physics/interpolation/img/fti_camera_worldspace.webp b/tutorials/physics/interpolation/img/fti_camera_worldspace.webp new file mode 100644 index 00000000000..b99ff8eeb80 Binary files /dev/null and b/tutorials/physics/interpolation/img/fti_camera_worldspace.webp differ diff --git a/tutorials/physics/interpolation/img/fti_graph_fixed_ticks.webp b/tutorials/physics/interpolation/img/fti_graph_fixed_ticks.webp new file mode 100644 index 00000000000..70d668aaf27 Binary files /dev/null and b/tutorials/physics/interpolation/img/fti_graph_fixed_ticks.webp differ diff --git a/tutorials/physics/interpolation/img/fti_graph_interpolated.webp b/tutorials/physics/interpolation/img/fti_graph_interpolated.webp new file mode 100644 index 00000000000..f20c71cd917 Binary files /dev/null and b/tutorials/physics/interpolation/img/fti_graph_interpolated.webp 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 00000000000..e66bbfbccda 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 00000000000..92ce6c24484 --- /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 00000000000..6969d4bb648 --- /dev/null +++ b/tutorials/physics/interpolation/physics_interpolation_introduction.rst @@ -0,0 +1,232 @@ +.. _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:`Project Settings > Physics > Common > Physics Tick per Second`), +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.webp + +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 deal with the problem, +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.webp + +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:: gdscript + + 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:: gdscript + + x_interpolated = x_prev + ((x_curr - x_prev) * 0.2) + +So substituting our ``x_prev`` as 10, and ``x_curr`` as 30: + +.. code-block:: gdscript + + 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 00000000000..0ba9fca7867 --- /dev/null +++ b/tutorials/physics/interpolation/physics_interpolation_quick_start_guide.rst @@ -0,0 +1,14 @@ +.. _doc_physics_interpolation_quick_start_guide: + +Quick start guide +================= + +- Turn on physics interpolation: :ref:`Project Settings > 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:`Project Settings > Physics > Common > Physics Tick per Second` + 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 00000000000..a97bed44fbf --- /dev/null +++ b/tutorials/physics/interpolation/using_physics_interpolation.rst @@ -0,0 +1,154 @@ +.. _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_ticks_per_second` + 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 behavior 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:`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.