From 44fa4a4cdefd90b456a2a11dc79f278fae6758a6 Mon Sep 17 00:00:00 2001 From: X23 <2284899547@qq.com> Date: Sat, 7 Feb 2026 16:37:15 +0800 Subject: [PATCH] Fix transform notification in threaded processing. --- scene/3d/node_3d.cpp | 5 +++-- scene/main/node.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 67cde94a31..b083a10035 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -122,10 +122,11 @@ void Node3D::_propagate_transform_changed(Node3D *p_origin) { #else if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) { #endif - if (likely(is_accessible_from_caller_thread())) { + // SceneTree::xform_change_list is not thread safe to modify, and is read by the main thread when processings are done. + if (Thread::is_main_thread()) { get_tree()->xform_change_list.add(&xform_change); } else { - // This should very rarely happen, but if it does at least make sure the notification is received eventually. + // For any threaded-processed node, add it to xform_change_list on the main thread in a deferred manner. callable_mp(this, &Node3D::_propagate_transform_changed_deferred).call_deferred(); } } diff --git a/scene/main/node.cpp b/scene/main/node.cpp index bcea29d2f1..3eb5cb6659 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1096,10 +1096,6 @@ void Node::_remove_tree_from_process_thread_group() { } void Node::_add_tree_to_process_thread_group(Node *p_owner) { - if (_is_any_processing()) { - _add_to_process_thread_group(); - } - data.process_thread_group_owner = p_owner; if (p_owner != nullptr) { data.process_group = p_owner->data.process_group; @@ -1107,12 +1103,16 @@ void Node::_add_tree_to_process_thread_group(Node *p_owner) { data.process_group = &data.tree->default_process_group; } + if (_is_any_processing()) { + _add_to_process_thread_group(); + } + for (KeyValue &K : data.children) { if (K.value->data.process_thread_group != PROCESS_THREAD_GROUP_INHERIT) { continue; } - K.value->_add_to_process_thread_group(); + K.value->_add_tree_to_process_thread_group(p_owner); } } bool Node::is_processing_internal() const {