# Conversion du personnage Mover vers le squelette MetaHuman Branche : `metahuman-skeleton-conversion` (dépôt `origin` = git.catrybenoit.dev/Dodo/ProjectFGame). Phase 1 (inventaire) faite le 2026-10-31. ## Cible - MetaHuman unique du projet : **« test »** - corps `/Game/Characters/MEtahuman/Unpacked/test/Body/SKM_test_BodyMesh`, squelette partagé `/Game/MetaHumans/Common/Female/Medium/NormalWeight/Body/metahuman_base_skel` ; - visage `SKM_test_FaceMesh` (squelette `Face_Archetype_Skeleton`, piloté par `ABP_Face`) ; - Physics Asset `PHYS_test` (les hitboxes du pion sont déjà calibrées dessus). - Source : `SK_UEFN_Mannequin` (squelette de `SKM_UEFN_Mannequin`). ## Inventaire ### Os | | UEFN | MetaHuman | |---|---|---| | Os | 95 | 342 | | Communs | 78, même hiérarchie | | Présents seulement côté UEFN, à ajouter au MetaHuman : - `ik_hand_root`, `ik_hand_gun`, `ik_hand_l`, `ik_hand_r` : IK des armes AST (`WeaponIKGraph` cible `VB hand_r_ik_hand_l`) ; - `ik_foot_root`, `ik_foot_l`, `ik_foot_r` : placement des pieds, `OverlayGraph::DynamicTransitionCheck` ; - `weapon_l`, `weapon_r`, `props_root`, `prop_01`, `attach`, `poi` ; - os virtuels : `VB hand_r_ik_hand_l`, `VB hand_l_ik_hand_r`, `VB hand_r_prop_01`, `VB hand_l_prop_01`. `unreal.SkeletonModifier` (add_bone / commit_skeleton_to_skeletal_mesh) est disponible en Python. ### Sockets à recréer (le MetaHuman n'en a aucun) 16 sockets UEFN : - `palm_l_Socket`, `palm_r_Socket` ; - `RagdollTrace` (`spine_03`) ; - `prop_01_Socket`, `VB hand_r_prop_01_Socket` ; - `BackpackSocket` (`spine_03`), `SpineRifle` (`spine_05`) ; - sur `hand_r` : `Bumper`, `Shotgun`, `FlashlightSocket`, `Rifle` ; - `weapon_r_muzzle` ; - sur `head` : `HeadphoneSocket`, `HelmetSocket` ; - `foot_l_Socket`, `foot_r_Socket`. ⚠️ Python ne sait pas nommer un socket : copier-coller dans l'éditeur de squelette (manuel, guidé), puis recaler les transforms par script. ### Assets qui référencent le squelette UEFN (2147) | Type | Nombre | Où | |---|---|---| | AnimSequence | 1845 | 1389 GASP (`Characters/UEFN_Mannequin`), 267 AST (`Systems/Movement`), 182 maison (`Assets/Animations/humain`), 7 AGIS | | AnimMontage | 224 | | | PoseSearchSchema | 30 | | | BlendSpace / 1D / AimOffset | 14 / 15 / 1 | | | AnimBlueprint | 8 | `SandboxCharacter_Mover_ABP`, `SandboxCharacter_CMC_ABP`, `ABP_AimingMaster_UEFN`, `ABP_UEFN_Mannequin_PostProcess`, `ABP_SkeletalEquippables`, 3 calques AST | | ControlRig | 4 | | | MirrorDataTable | 3 | | Dépendants indirects (référencent des anims, pas le squelette) : 185 bases Motion Matching, 25 choosers. ## Approche retenue : retarget en lot + remplacement des références 1. **Squelette MetaHuman** - Ajouter les 17 os manquants via `SkeletonModifier`. - Ajouter les 4 os virtuels et les sockets. - Ajouter les groupes de slots d'animation (`Grounded Slot`…) via l'Anim Slot Manager, à la main. 2. **Retargeter dédié au lot** (`RTG_UEFN_to_MH_Batch`), distinct de celui du runtime : - doigts en `OneToOne` avec la pose de retarget alignée (déjà réglé sur `RTG_UEFN_to_MetaHuman_test`) ; - pieds et jambes : objectifs IK mis à l'échelle ; - os IK : - `ik_foot_*` épinglés aux pieds ; - `ik_hand_gun` épinglé à `hand_r` en gardant l'écart source **sans mise à l'échelle** : l'arme garde sa taille, donc les cibles de main sur l'arme aussi ; - `ik_hand_l` / `ik_hand_r` copiés en local. 3. **Retarget en lot** (`IKRetargetBatchOperation`), par blocs d'environ 200 assets avec sauvegarde entre chaque : - séquences, montages, blend spaces, aim offset et miroirs, dans un dossier miroir `Content/Characters/MH/…` ; - les références internes sont conservées (un montage pointe vers sa séquence convertie). 4. **Remplacement des références** ancien → nouveau, pour que les 185 bases, les 25 choosers, les ABP et les notifies suivent sans être dupliqués. - Valider d'abord sur un petit lot. - Piège connu : `consolidate_assets` a déjà cassé des variables enum/struct ; contrôler avant de recharger. 5. **Schémas Motion Matching** passés sur le nouveau squelette, puis reconstruction des index des 185 bases. 6. **AnimBP et calques** retargetés sur `metahuman_base_skel`. Les Control Rigs travaillent par nom d'os, donc peu d'impact attendu. Recaler l'offset de la main gauche de `WeaponIKGraph`. 7. **Pion `SandboxCharacter_Mover`** - mesh = `SKM_test_BodyMesh`, avec `Face` en enfant et le `MetaHumanComponent` ; - nouvel ABP ; - suppression de l'override visuel (`VisualOverride`, `AC_VisualOverrideManager`, `ABP_GenericRetarget`) ; - `Inventory_Equipper` revient à l'attache simple. 8. **Tests** : - déplacements (Motion Matching), transitions ; - arc, fusil (visée, main gauche) ; - prone, nage, cover, interactions AST, push ; - mort et ragdoll, portrait d'inventaire, capture des hitboxes. 9. **Nettoyage** : suppression du contenu UEFN seulement après validation (« compiler d'abord, nettoyer ensuite »). ## Avancement - **Phase 2 faite (2026-10-31)** — squelette MetaHuman : - **13 os ajoutés** par `SkeletonModifier` (342 → 355), calés sur la pose du MetaHuman : - `ik_foot_l/r` sur les pieds ; - `ik_hand_gun` et `ik_hand_r` sur `hand_r`, `ik_hand_l` sur `hand_l` ; - `weapon_l/r` avec le même décalage local que l'UEFN ; - `props_root`, `prop_01`, `attach` à l'origine, `poi` en (0, 150, 152.05). - **4 os virtuels** aux noms identiques à l'UEFN. `add_virtual_bone` exige une `AnimSequence` du squelette : une anim temporaire a été créée puis supprimée. - **16 sockets** copiés-collés à la main depuis l'UEFN, vérifiés par script : même os, même position relative. - Écarts en pose de référence : - sockets de main tournés de ~20°, parce que les mains du MetaHuman sont orientées autrement au repos. Le retargeter de conversion doit copier la rotation des mains depuis la source (`BlendToSourceRotation` = 1 sur `LeftArm`/`RightArm`), comme au runtime ; - casque ~10 cm plus haut (taille), sac à dos 7 cm plus près du dos : à vérifier à l'œil. - Sauvegarde : `E:\projet\ProjectFv1_backup_mh_conversion_2026-10-31\`. - Non-régression en PIE avec l'override actuel : visée OK, 0 erreur. - Groupes de slots : reportés après la conversion des montages, qui ajoute les slots au squelette. - **Phase 3 faite (2026-10-31)** — conversion des animations : - **Retargeters** de conversion dans `Characters/MH/Retarget/` : - `RTG_UEFN_to_MH_Batch` (général) : copie de `RTG_UEFN_to_MetaHuman_test` + Root Motion sur l'os `root` de la source (`set_source_root_bone("root")`, l'ancien réglage `pelvis` faisait monter `root` à 91 cm) + Pin Bones (`ik_foot_*` ← pieds, `ik_hand_gun`/`ik_hand_r` ← `hand_r`, `ik_hand_l` ← `hand_l`, via `set_bone_pair`). - `RTG_UEFN_to_MH_Weapon` (armes AST) : en plus, op **Weapon Goals** (échelle 1) avant Run IK Rig ; IK Rigs dédiés `IK_UEFN_Batch` / `IK_MH_Batch` avec les chaînes `IKHandGun`/`IKHandL`/`IKHandR` (FK `OneToOne` + translation `Absolute`) ; pose de retarget de `ik_hand_gun` tournée de (P 17.6, Y -5.3, R 10.2) pour compenser l'écart de pose de repos des mains. - Bras : `BlendToSource` 1 / translation 0 / rotation 1. - **Contrôles** sur `SMG_Aim_Pose` et `M_Neutral_Run_Loop_F` : - main gauche à l'identique par rapport à la main droite (32,9 cm) ; - rotation des mains à moins de 1° de la source ; - racine au sol, avancée identique, pieds IK collés. - **2099 assets convertis**, 0 échec, ~10 min : - 1845 séquences, 224 montages, 29 blend spaces, 1 aim offset ; - armes AST = noms SMG/Handgun/Sniper/Bullpup/Shotgun/Pistol/Rifle sous `Systems/Movement`. - **Rangement** : copies `_MH` créées à côté des originaux, puis déplacées dans `Content/Characters/MH/` sans le suffixe. Montages et blend spaces pointent tous vers les copies (227 segments, 237 échantillons vérifiés). - Scripts et journal : `p3_batch.py`, `p3_state.json`, `p3_move.py` dans le scratchpad de la session. - **Reste à faire avant les AnimBP** : - **groupes de slots** du squelette MetaHuman, à la main dans l'Anim Slot Manager (protégés en Python). Slots utilisés : `DefaultSlot`, `UpperBody`, `Curves`, `Spine`, `Head`, `Arm L`, `Arm R`, `Pelvis`, `Fire`, `Grounded Slot` (groupe `GroundedGroup`), `HitReactionSlot`. Recopier la répartition du mannequin ; - **Blend Profiles** du squelette UEFN (`FastFeet`…, utilisés par l'ABP GASP) à recréer sur le MetaHuman. - Non converties : 3 `MirrorDataTable`, à refaire pour le squelette MetaHuman (miroir des anims prone/nage et GASP). - **Phase 4 (2026-10-31 → 2026-11-04)** — remplacement des références : - `consolidate_assets(MH, [UEFN])` sur les 2099 assets, par lots de 100 avec sauvegarde entre chaque (~2 h 15). - L'éditeur affiche « Critical Failure to Consolidate Assets » et demande un redémarrage sans sauvegarde ; les références sont pourtant remplacées et enregistrées. - Effet réel : l'original UEFN devient un **redirecteur** vers la version MH (1963 sur 2099). - 136 n'ont pas été remplacés au premier passage (encore chargés en mémoire) ; relancés après redémarrage. Les 2099 sont maintenant des redirecteurs. - Python n'a pas de correction des redirecteurs : les 226 assets qui passaient encore par eux ont été réenregistrés, ils pointent directement vers `Characters/MH`. Plus aucun référenceur hors de la liste des 2099. Les redirecteurs partent avec le dossier UEFN au nettoyage. - **Doublons** : la consolidation a fait rajouter des montages par leurs notifies Branch In dans 4 bases (`PSD_Traversal` +3, `PSD_SM_CMC_Idles` +2, `_Loops` +10, `_Transitions` +32). Bases restaurées depuis le commit (éditeur fermé), puis réenregistrées. - **Contrôle final** : 185 bases, 2705 entrées toutes MetaHuman, 0 doublon ; 24 assets d'interaction sur les anims MH. Les index se reconstruisent à la première utilisation (pas d'API Python) → à vérifier en PIE. - **Table miroir MetaHuman** : `Characters/MH/Characters/UEFN_Mannequin/Rigs/MDT_UEFN_Mannequin`. - Mêmes règles de recherche/remplacement que l'UEFN, 355 lignes (349 paires gauche/droite, 6 os centraux sur eux-mêmes). - Piège : `fill_data_table_from_json_string` remet le squelette à vide, il faut le régler après. - `MiroiDtCover` (pion CMC seulement) et `MDT_uefn` (inutilisée) ne sont pas convertis. - **30 schémas Motion Matching** passés sur `metahuman_base_skel` (`ToolsetLibrary.set_object_properties` sur `Skeletons`), `PSS_Default`/`PSS_Idle` avec la nouvelle table miroir. - **Phase 5 faite (2026-11-05)** — squelette et AnimBP : - **Slots** recréés à la main (Anim Slot Manager) : `DefaultGroup` + `GroundedGroup` (`Grounded Slot`). - **9 Blend Profiles** recréés par `unreal.SkeletonService` (VibeUE : `create_blend_profile` / `set_blend_profile_bone`). - Os MetaHuman en plus (twists, correctifs, orteils) : valeur de l'os parent présent sur l'UEFN. - VibeUE crée en type *Weight* ; le type n'est pas modifiable en Python. Recréés à la main en *Time* (`Pivot`, `FastFeet`, `FastFeet_InstantRoot`, `FastFeet_FastRoot`) et en masque (`UpperBody`), puis remplis par script. - Masque : valeur par défaut 0 (`UBlendProfile::GetDefaultBlendScale`), donc le `UpperBody` MH (359 os à 0) équivaut à celui de l'UEFN. - **32 montages MH** pointaient encore vers `SK_UEFN_Mannequin:FastFeet_InstantRoot` (`blend_profile_in/out`) → profil MH du même nom. - **Table miroir** : `MDT_UEFN_Mannequin` consolidée vers la version MH (ABP Mover, `OverrideOverlayLayer`, schémas). - **5 AnimBP passés en place** sur `metahuman_base_skel` (`set_editor_property("target_skeleton")`) puis compilés : `SandboxCharacter_Mover_ABP`, `OverlayGraph`, `OverrideOverlayLayer`, `InteractionIKGraph`, `ABP_AimingMaster_UEFN`. - Blend Profiles des nœuds rebranchés (`ObjectIterator(AnimGraphNode_Base)`, `node.blend_profile`) : Motion Matching → `FastFeet_InstantRoot`, Blend by Bool → `FastHead_Weight`. - Compilation dans l'ordre calques → ABP principal : 0 erreur. Reste l'avertissement `VB RHS_WeaponTrace` absent dans `OverlayGraph`, déjà présent avant (os absent de l'UEFN aussi). - **Non touchés** : - `ABP_UEFN_Mannequin_PostProcess` (mesh UEFN) ; - `SandboxCharacter_CMC_ABP` (supprimé au nettoyage) ; - `ABP_SkeletalEquippables` (utilisé par `ItemMesh_Skeletal`, à voir selon le squelette des items). - **Control Rigs** (`CR_UEFN_Mannequin_FullBodyIK`, pieds, escalade, interaction, collision d'arme) : gardent la hiérarchie UEFN, mêmes noms d'os → à valider en PIE ; réimporter la hiérarchie MH si besoin. - Recalage de la main gauche de `WeaponIKGraph` : reporté après la phase 6 (il faut le pion MetaHuman en PIE). - **Phase 6 (2026-11-05)** — pion `SandboxCharacter_Mover` sur le MetaHuman : - `SkeletalMesh` = `SKM_test_BodyMesh`, AnimBP `SandboxCharacter_Mover_ABP`. - Le composant était en mode **Animation Single Node** (idle en boucle) : repassé en `AnimationBlueprint`. - Ajout de `Face` (enfant de `SkeletalMesh`, `SKM_test_FaceMesh` + `ABP_Face`) et du composant `MetaHuman` (`MetaHumanComponentUE`), réglages copiés de `BP_VisualOverride_MetaHuman`, `bodyComponentName` = `SkeletalMesh`. - Composant `VisualOverride` retiré. Les systèmes qui en dépendaient retombent sur le mesh du pion : - `AC_VisualOverrideManager` : boucle vide, les hitboxes restent sur `SkeletalMesh` (déjà calibrées sur `PHYS_test`) ; - `BP_Item_OutfitPiece_Base` : branche sans override → `GetComponentByClass(SkeletalMeshComponent)` = `SkeletalMesh` (vérifié en PIE) ; - portrait d'inventaire : `ShowOnlyActorComponents(self)` inclut corps et visage. - `Inventory_Equipper::Attach Item to Owner` : bloc de réattache au `Body` du MetaHuman supprimé (17 nœuds), l'arme reste sur le socket du mesh du pion. - PIE (MapDev1) : AnimBP actif, 2 m parcourus en 3 s de marche, fusil sur le socket `Rifle` du MetaHuman, visée OK, 0 erreur. Mains écartées de 38,6 cm en visée (32,9 dans l'anim source) → recalage de la main gauche à faire. - Restent pour le nettoyage : `AC_VisualOverrideManager`, `BP_VisualOverride_MetaHuman`, `ABP_GenericRetarget`, `RTG_UEFN_to_MetaHuman_test`, `IK_MetaHuman_test`, CVar `DDCvar.VisualOverride`, `IA_NextVisualOverride`. ## Décisions (validées le 2026-10-31) - Assets convertis dans le dossier miroir **`Content/Characters/MH/…`** ; le contenu UEFN est supprimé à la fin. - **`SandboxCharacter_CMC` est supprimé** au nettoyage final (non converti). - **Les 17 os manquants sont ajoutés au MetaHuman** (`SKM_test_BodyMesh` + `metahuman_base_skel`).