diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 1ea342c3f441..fe19042e4544 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -685,37 +685,43 @@ void TileMapLayer::_physics_update() { } void TileMapLayer::_physics_notify_tilemap_change(TileMapLayer::DirtyFlags p_what) { - Transform2D gl_transform = tile_map_node->get_global_transform(); + if (!tile_map_node->is_inside_tree()) { + return; + } + + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); + bool in_editor = false; #ifdef TOOLS_ENABLED in_editor = Engine::get_singleton()->is_editor_hint(); #endif - if (p_what == DIRTY_FLAGS_TILE_MAP_XFORM) { - if (tile_map_node->is_inside_tree() && (!tile_map_node->is_collision_animatable() || in_editor)) { - for (KeyValue &kv : tile_map) { - const CellData &cell_data = kv.value; + if ( + (p_what == DIRTY_FLAGS_TILE_MAP_XFORM && (!tile_map_node->is_collision_animatable() || in_editor)) || + (p_what == DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM && (tile_map_node->is_collision_animatable() && !in_editor))) { + Transform2D gl_transform = tile_map_node->get_global_transform(); - for (RID body : cell_data.bodies) { - if (body.is_valid()) { - Transform2D xform(0, tile_map_node->map_to_local(bodies_coords[body])); - xform = gl_transform * xform; - PhysicsServer2D::get_singleton()->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); - } + for (KeyValue &kv : tile_map) { + const CellData &cell_data = kv.value; + + for (RID body : cell_data.bodies) { + if (body.is_valid()) { + Transform2D xform(0, tile_map_node->map_to_local(bodies_coords[body])); + xform = gl_transform * xform; + ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); } } } - } else if (p_what == DIRTY_FLAGS_TILE_MAP_LOCAL_XFORM) { - if (tile_map_node->is_inside_tree() && tile_map_node->is_collision_animatable() && !in_editor) { - for (KeyValue &kv : tile_map) { - const CellData &cell_data = kv.value; + } else if (p_what == DIRTY_FLAGS_TILE_MAP_IN_TREE) { + // Changes in the tree may cause the space to change (e.g. when reparenting to a SubViewport) + RID space = tile_map_node->get_world_2d()->get_space(); - for (RID body : cell_data.bodies) { - if (body.is_valid()) { - Transform2D xform(0, tile_map_node->map_to_local(bodies_coords[body])); - xform = gl_transform * xform; - PhysicsServer2D::get_singleton()->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); - } + for (KeyValue &kv : tile_map) { + const CellData &cell_data = kv.value; + + for (RID body : cell_data.bodies) { + if (body.is_valid()) { + ps->body_set_space(body, space); } } }