diff --git a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp index 1e15b16d21..2e3e226c34 100644 --- a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp +++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp @@ -730,13 +730,34 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory } String track_path = String(anim->track_get_path(i).get_concatenated_names()); - Node *node = (ap->get_node(ap->get_root_node()))->get_node(NodePath(track_path)); - ERR_CONTINUE(!node); + + // [TINQS] Fix: %UniqueNode resolution fails in headless/import context. + // Fall back to find_child when get_node fails (e.g., headless --import). + Node *node = nullptr; + Node *anim_root = ap->get_node_or_null(ap->get_root_node()); + if (anim_root) { + node = anim_root->get_node_or_null(NodePath(track_path)); + } + if (!node && track_path.begins_with(UNIQUE_NODE_PREFIX)) { + // Unique name resolution failed — try direct child search. + String skel_name = track_path.substr(1); // Strip % prefix. + node = p_base_scene->find_child(skel_name, true, false); + if (node) { + print_verbose(vformat("[RetargetRestFixer] Resolved '%s' via find_child fallback -> '%s'", track_path, node->get_name())); + } else { + WARN_PRINT(vformat("[RetargetRestFixer] Failed to resolve skeleton node '%s' — animation keyframes will NOT be converted to new rest pose. This may cause incorrect bone orientations.", track_path)); + } + } + if (!node) { + WARN_PRINT(vformat("[RetargetRestFixer] Skipping track %d: cannot resolve node path '%s' from AnimationPlayer root.", i, track_path)); + continue; + } Skeleton3D *track_skeleton = Object::cast_to(node); if (!track_skeleton || (is_using_modifier && track_skeleton != profile_skeleton && track_skeleton != orig_skeleton) || (!is_using_modifier && track_skeleton != src_skeleton)) { + print_verbose(vformat("[RetargetRestFixer] Skipping track %d: skeleton mismatch (found '%s', expected src_skeleton).", i, node->get_name())); continue; } @@ -746,6 +767,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory } int bone_idx = src_skeleton->find_bone(bn); + print_verbose(vformat("[RetargetRestFixer] Converting track %d bone '%s' (idx=%d) — %d keys", i, bn, bone_idx, anim->track_get_key_count(i))); if (is_using_modifier) { int prof_idx = profile->find_bone(bn);