advanced_physics_interpolation.rst 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. .. _doc_advanced_physics_interpolation:
  2. Advanced physics interpolation
  3. ==============================
  4. Although the previous instructions will give satisfactory results in a lot of games,
  5. in some cases you will want to go a stage further to get the best possible results
  6. and the smoothest possible experience.
  7. Exceptions to automatic physics interpolation
  8. ---------------------------------------------
  9. Even with physics interpolation active, there may be some local situations where
  10. you would benefit from disabling automatic interpolation for a
  11. :ref:`Node<class_Node>` (or branch of the :ref:`SceneTree<class_SceneTree>`), and
  12. have the finer control of performing interpolation manually.
  13. This is possible using the :ref:`Node.physics_interpolation_mode<class_Node_property_physics_interpolation_mode>`
  14. property which is present in all Nodes. If you for example, turn off interpolation
  15. for a Node, the children will recursively also be affected (as they default to
  16. inheriting the parent setting). This means you can easily disable interpolation for
  17. an entire subscene.
  18. The most common situation where you may want to perform your own interpolation is
  19. Cameras.
  20. Cameras
  21. ~~~~~~~
  22. In many cases, a :ref:`Camera3D<class_Camera3D>` can use automatic interpolation
  23. just like any other node. However, for best results, especially at low physics tick
  24. rates, it is recommended that you take a manual approach to camera interpolation.
  25. This is because viewers are very sensitive to camera movement. For instance, a
  26. Camera3D that realigns slightly every 1/10th of a second (at 10tps tick rate) will
  27. often be noticeable. You can get a much smoother result by moving the camera each
  28. frame in ``_process``, and following an interpolated target manually.
  29. Manual camera interpolation
  30. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  31. Ensure the camera is using global coordinate space
  32. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  33. The very first step when performing manual camera interpolation is to make sure the
  34. Camera3D transform is specified in *global space* rather than inheriting the
  35. transform of a moving parent. This is because feedback can occur between the
  36. movement of a parent node of a Camera3D and the movement of the camera Node itself,
  37. which can mess up the interpolation.
  38. There are two ways of doing this:
  39. 1) Move the Camera3D so it is independent on its own branch, rather than being a child of a moving object.
  40. .. image:: img/fti_camera_worldspace.webp
  41. 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.
  42. Typical example
  43. ^^^^^^^^^^^^^^^
  44. A typical example of a custom approach is to use the ``look_at`` function in the
  45. Camera3D every frame in ``_process()`` to look at a target node (such as the player).
  46. But there is a problem. If we use the traditional ``get_global_transform()`` on a
  47. Camera3D "target" node, this transform will only focus the Camera3D on the target *at
  48. the current physics tick*. This is *not* what we want, as the camera will jump
  49. about on each physics tick as the target moves. Even though the camera may be
  50. updated each frame, this does not help give smooth motion if the *target* is only
  51. changing each physics tick.
  52. get_global_transform_interpolated()
  53. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  54. What we really want to focus the camera on, is not the position of the target on
  55. the physics tick, but the *interpolated* position, i.e. the position at which the
  56. target will be rendered.
  57. We can do this using the :ref:`Node3D.get_global_transform_interpolated<class_Node3D_method_get_global_transform_interpolated>`
  58. function. This acts exactly like getting :ref:`Node3D.global_transform<class_Node3D_property_global_transform>`
  59. but it gives you the *interpolated* transform (during a ``_process()`` call).
  60. .. important:: ``get_global_transform_interpolated()`` should only be used once or
  61. twice for special cases such as cameras. It should **not** be used
  62. all over the place in your code (both for performance reasons, and
  63. to give correct gameplay).
  64. .. note:: Aside from exceptions like the camera, in most cases, your game logic
  65. should be in ``_physics_process()``. In game logic you should be calling
  66. ``get_global_transform()`` or ``get_transform()``, which will give the
  67. current physics transform (in global or local space respectively), which
  68. is usually what you will want for gameplay code.
  69. Example manual camera script
  70. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  71. Here is an example of a simple fixed camera which follows an interpolated target:
  72. .. code-block:: gdscript
  73. extends Camera3D
  74. # Node that the camera will follow
  75. var _target
  76. # We will smoothly lerp to follow the target
  77. # rather than follow exactly
  78. var _target_pos : Vector3 = Vector3()
  79. func _ready() -> void:
  80. # Find the target node
  81. _target = get_node("../Player")
  82. # Turn off automatic physics interpolation for the Camera3D,
  83. # we will be doing this manually
  84. set_physics_interpolation_mode(Node.PHYSICS_INTERPOLATION_MODE_OFF)
  85. func _process(delta: float) -> void:
  86. # Find the current interpolated transform of the target
  87. var tr : Transform = _target.get_global_transform_interpolated()
  88. # Provide some delayed smoothed lerping towards the target position
  89. _target_pos = lerp(_target_pos, tr.origin, min(delta, 1.0))
  90. # Fixed camera position, but it will follow the target
  91. look_at(_target_pos, Vector3(0, 1, 0))
  92. Mouse look
  93. ^^^^^^^^^^
  94. Mouse look is a very common way of controlling cameras. But there is a problem.
  95. Unlike keyboard input which can be sampled periodically on the physics tick, mouse
  96. move events can come in continuously. The camera will be expected to react and
  97. follow these mouse movements on the next frame, rather than waiting until the next
  98. physics tick.
  99. In this situation, it can be better to disable physics interpolation for the camera
  100. node (using :ref:`Node.physics_interpolation_mode<class_Node_property_physics_interpolation_mode>`)
  101. and directly apply the mouse input to the camera rotation, rather than apply it in
  102. ``_physics_process``.
  103. Sometimes, especially with cameras, you will want to use a combination of
  104. interpolation and non-interpolation:
  105. - A first person camera may position the camera at a player location (perhaps using
  106. :ref:`Node3D.get_global_transform_interpolated<class_Node3D_method_get_global_transform_interpolated>`),
  107. but control the Camera rotation from mouse look *without* interpolation.
  108. - A third person camera may similarly determine the look at (target location) of the camera using
  109. :ref:`Node3D.get_global_transform_interpolated<class_Node3D_method_get_global_transform_interpolated>`,
  110. but position the camera using mouse look *without* interpolation.
  111. There are many permutations and variations of camera types, but it should be clear
  112. that in many cases, disabling automatic physics interpolation and handling this
  113. yourself can give a better result.
  114. Disabling interpolation on other nodes
  115. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  116. Although cameras are the most common example, there are a number of cases when you
  117. may wish other nodes to control their own interpolation, or be non-interpolated.
  118. Consider for example, a player in a top view game whose rotation is controlled by
  119. mouse look. Disabling physics rotation allows the player rotation to match the
  120. mouse in real-time.
  121. MultiMeshes
  122. ~~~~~~~~~~~
  123. Although most visual Nodes follow the single Node single visual instance paradigm,
  124. MultiMeshes can control several instances from the same Node. Therefore, they have
  125. some extra functions for controlling interpolation functionality on a
  126. *per-instance* basis. You should explore these functions if you are using
  127. interpolated MultiMeshes.
  128. - :ref:`MultiMesh.reset_instance_physics_interpolation<class_MultiMesh_method_reset_instance_physics_interpolation>`
  129. - :ref:`MultiMesh.set_buffer_interpolated<class_MultiMesh_method_set_buffer_interpolated>`
  130. Full details are in the :ref:`MultiMesh<class_MultiMesh>` documentation.