diff --git a/doc/classes/Spatial.xml b/doc/classes/Spatial.xml
index 97c566bc552..db206cf9f68 100644
--- a/doc/classes/Spatial.xml
+++ b/doc/classes/Spatial.xml
@@ -24,6 +24,7 @@
When using physics interpolation, there will be circumstances in which you want to know the interpolated (displayed) transform of a node rather than the standard transform (which may only be accurate to the most recent physics tick).
This is particularly important for frame-based operations that take place in [method Node._process], rather than [method Node._physics_process]. Examples include [Camera]s focusing on a node, or finding where to fire lasers from on a frame rather than physics tick.
+ [b]Note:[/b] This function creates an interpolation pump on the [Spatial] the first time it is called, which can respond to physics interpolation resets. If you get problems with "streaking" when initially following a [Spatial], be sure to call [method get_global_transform_interpolated] at least once [i]before[/i] resetting the [Spatial] physics interpolation.
diff --git a/main/main.cpp b/main/main.cpp
index 37e386e6f87..9553e90bc53 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2367,14 +2367,14 @@ bool Main::iteration() {
uint64_t physics_begin = OS::get_singleton()->get_ticks_usec();
- PhysicsServer::get_singleton()->flush_queries();
-
// Prepare the fixed timestep interpolated nodes
- // BEFORE they are updated by the physics 2D,
+ // BEFORE they are updated by the physics,
// otherwise the current and previous transforms
// may be the same, and no interpolation takes place.
OS::get_singleton()->get_main_loop()->iteration_prepare();
+ PhysicsServer::get_singleton()->flush_queries();
+
Physics2DServer::get_singleton()->sync();
Physics2DServer::get_singleton()->flush_queries();
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 60b729467ce..cac9673bfa0 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -407,7 +407,14 @@ Transform Spatial::get_global_transform_interpolated() {
// Pass through if physics interpolation is switched off.
// This is a convenience, as it allows you to easy turn off interpolation
// without changing any code.
- if (Engine::get_singleton()->is_in_physics_frame() || !is_physics_interpolated_and_enabled()) {
+ if (!is_physics_interpolated_and_enabled()) {
+ return get_global_transform();
+ }
+
+ // If we are in the physics frame, the interpolated global transform is meaningless.
+ // However, there is an exception, we may want to use this as a means of starting off the client
+ // interpolation pump if not already started (when _is_physics_interpolated_client_side() is false).
+ if (Engine::get_singleton()->is_in_physics_frame() && _is_physics_interpolated_client_side()) {
return get_global_transform();
}
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 48335922454..3c1809c3586 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -559,6 +559,11 @@ void SceneTree::iteration_prepare() {
// are flushed before pumping the interpolation prev and currents.
flush_transform_notifications();
VisualServer::get_singleton()->tick();
+
+ // Any objects performing client physics interpolation
+ // should be given an opportunity to keep their previous transforms
+ // up to date before each new physics tick.
+ _client_physics_interpolation.physics_process();
}
}
@@ -575,11 +580,6 @@ bool SceneTree::iteration(float p_time) {
current_frame++;
- // Any objects performing client physics interpolation
- // should be given an opportunity to keep their previous transforms
- // up to take before each new physics tick.
- _client_physics_interpolation.physics_process();
-
flush_transform_notifications();
if (MainLoop::iteration(p_time)) {