- CHT_PoseSearchDatabases_Mover : la ligne « Prone Moving » demandait la stance Debout ; les lignes prone acceptent toute gait (la gait ne passe à Prone qu'après la stance) - SandboxCharacter_Mover_ABP : condition GASP d'interruption du Motion Matching sur changement d'état, de gait ou de stance rebranchée - bilan des tests PIE dans le plan : locomotion, traversées, prone, fusil, ragdoll physique, portrait OK ; cover, interactions, nage, arc et mort à vérifier à la main Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
18 KiB
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(squeletteFace_Archetype_Skeleton, piloté parABP_Face) ; - Physics Asset
PHYS_test(les hitboxes du pion sont déjà calibrées dessus).
- corps
- Source :
SK_UEFN_Mannequin(squelette deSKM_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 (WeaponIKGraphcibleVB 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
- 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.
- Ajouter les 17 os manquants via
- Retargeter dédié au lot (
RTG_UEFN_to_MH_Batch), distinct de celui du runtime :- doigts en
OneToOneavec la pose de retarget alignée (déjà réglé surRTG_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_ren 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_rcopiés en local.
- doigts en
- 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).
- séquences, montages, blend spaces, aim offset et miroirs, dans un dossier miroir
- 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_assetsa déjà cassé des variables enum/struct ; contrôler avant de recharger.
- Schémas Motion Matching passés sur le nouveau squelette, puis reconstruction des index des 185 bases.
- 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 deWeaponIKGraph. - Pion
SandboxCharacter_Mover- mesh =
SKM_test_BodyMesh, avecFaceen enfant et leMetaHumanComponent; - nouvel ABP ;
- suppression de l'override visuel (
VisualOverride,AC_VisualOverrideManager,ABP_GenericRetarget) ; Inventory_Equipperrevient à l'attache simple.
- mesh =
- 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.
- 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/rsur les pieds ;ik_hand_gunetik_hand_rsurhand_r,ik_hand_lsurhand_l;weapon_l/ravec le même décalage local que l'UEFN ;props_root,prop_01,attachà l'origine,poien (0, 150, 152.05).
- 4 os virtuels aux noms identiques à l'UEFN.
add_virtual_boneexige uneAnimSequencedu 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 surLeftArm/RightArm), comme au runtime ; - casque ~10 cm plus haut (taille), sac à dos 7 cm plus près du dos : à vérifier à l'œil.
- 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 (
- 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.
- 13 os ajoutés par
-
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 deRTG_UEFN_to_MetaHuman_test+ Root Motion sur l'osrootde la source (set_source_root_bone("root"), l'ancien réglagepelvisfaisait monterrootà 91 cm) + Pin Bones (ik_foot_*← pieds,ik_hand_gun/ik_hand_r←hand_r,ik_hand_l←hand_l, viaset_bone_pair).RTG_UEFN_to_MH_Weapon(armes AST) : en plus, op Weapon Goals (échelle 1) avant Run IK Rig ; IK Rigs dédiésIK_UEFN_Batch/IK_MH_Batchavec les chaînesIKHandGun/IKHandL/IKHandR(FKOneToOne+ translationAbsolute) ; pose de retarget deik_hand_guntournée de (P 17.6, Y -5.3, R 10.2) pour compenser l'écart de pose de repos des mains.- Bras :
BlendToSource1 / translation 0 / rotation 1.
- Contrôles sur
SMG_Aim_PoseetM_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
_MHcréées à côté des originaux, puis déplacées dansContent/Characters/MH/<chemin d'origine>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.pydans 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(groupeGroundedGroup),HitReactionSlot. Recopier la répartition du mannequin ; - Blend Profiles du squelette UEFN (
FastFeet…, utilisés par l'ABP GASP) à recréer sur le MetaHuman.
- groupes de slots du squelette MetaHuman, à la main dans l'Anim Slot Manager (protégés en Python). Slots utilisés :
- Non converties : 3
MirrorDataTable, à refaire pour le squelette MetaHuman (miroir des anims prone/nage et GASP).
- Retargeters de conversion dans
-
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_stringremet le squelette à vide, il faut le régler après. MiroiDtCover(pion CMC seulement) etMDT_uefn(inutilisée) ne sont pas convertis.
- 30 schémas Motion Matching passés sur
metahuman_base_skel(ToolsetLibrary.set_object_propertiessurSkeletons),PSS_Default/PSS_Idleavec 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 leUpperBodyMH (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_Mannequinconsolidé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_WeaponTraceabsent dansOverlayGraph, déjà présent avant (os absent de l'UEFN aussi).
- Blend Profiles des nœuds rebranchés (
- Non touchés :
ABP_UEFN_Mannequin_PostProcess(mesh UEFN) ;SandboxCharacter_CMC_ABP(supprimé au nettoyage) ;ABP_SkeletalEquippables(utilisé parItemMesh_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).
- Slots recréés à la main (Anim Slot Manager) :
-
Phase 6 (2026-11-05) — pion
SandboxCharacter_Moversur le MetaHuman :SkeletalMesh=SKM_test_BodyMesh, AnimBPSandboxCharacter_Mover_ABP.- Le composant était en mode Animation Single Node (idle en boucle) : repassé en
AnimationBlueprint.
- Le composant était en mode Animation Single Node (idle en boucle) : repassé en
- Ajout de
Face(enfant deSkeletalMesh,SKM_test_FaceMesh+ABP_Face) et du composantMetaHuman(MetaHumanComponentUE), réglages copiés deBP_VisualOverride_MetaHuman,bodyComponentName=SkeletalMesh. - Composant
VisualOverrideretiré. Les systèmes qui en dépendaient retombent sur le mesh du pion :AC_VisualOverrideManager: boucle vide, les hitboxes restent surSkeletalMesh(déjà calibrées surPHYS_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 auBodydu 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
Rifledu 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. - Bug escalade (2026-11-05) : sur un bloc de 2 m le perso montait à 3,43 m.
- Cause : les warps de traversée (
FrontLedge…) utilisent l'osattachcomme repère (WarpPointAnimProvider = Bone). Il n'était pas animé dans les séquences converties (ni chaîne ni pin dans le RTG) → resté à la racine. - Correction : piste
attachrecopiée image par image depuis les originaux demaindans les 70 séquences concernées (73 montages : Climb, Mantle, Vault, Hurdle, Catch, Bench) viaAnimSequencerController.set_bone_track_keys. - Après modification d'anims, l'index interne du chooser
CHT_TraversalMontages_Moverreste « annulé » jusqu'au redémarrage de l'éditeur. - Vérifié sur une map de test : mantle 1 m et 1,5 m, escalade 2 m et 2,4 m, le perso finit à la hauteur du bloc.
- Cause : les warps de traversée (
- Restent pour le nettoyage :
AC_VisualOverrideManager,BP_VisualOverride_MetaHuman,ABP_GenericRetarget,RTG_UEFN_to_MetaHuman_test,IK_MetaHuman_test, CVarDDCvar.VisualOverride,IA_NextVisualOverride.
-
Phase 7 (2026-11-05) — tests en PIE, pilotés par script (entrées Enhanced Input injectées, relevés à chaque frame) :
- OK :
- course 3,7 m/s, accroupi 1,7 m/s, sprint 5,85 m/s, saut en sprint, réception ;
- mantle 1 m / 1,5 m, escalade 2 m / 2,4 m (après correction de
attach) ; - prone à l'arrêt (
PSD_Dense_Prone_Idles) ; - fusil sur le socket
Rifledu MetaHuman, main gauche à 5 cm du socketLH_IK(écart poignet-paume), identique en visée → recalage non nécessaire ; - ragdoll physique sur
PHYS_test(corps au sol, visage qui suit, hitbox de tête à 6 cm) ; - portrait d'inventaire (silhouette complète dans
RT_CharacterView) ; - aucune nouvelle erreur au journal.
- Problèmes trouvés, a priori antérieurs à la conversion :
- reptation en prone :
ValidDatabases= 0 pendant le déplacement → pose quasi debout. Le chooserCHT_PoseSearchDatabases_Moversignale depuis le 31/10 des liaisons introuvables (Cover,Cover Direction,WantToSwinSpr) ; - le 2e appui sur crouch ne relève pas le perso (C partagé entre crouch et prone) ;
IA_TriggerRagdoll(R) n'est pas géré par le pion Mover ;- « Divide by zero » dans
AC_TraversalLogicpendant les traversées.
- reptation en prone :
- Reptation corrigée : dans
CHT_PoseSearchDatabases_Mover, la ligne racine « Prone Moving » demandaitStance = Stand(E_Stance::NewEnumerator0) au lieu deProne→ passée àNewEnumerator2(viaToolsetLibrary.set_object_propertiessurColumnsStructs, seule différence à l'export T3D). En PIE :PSD_Dense_Prone_Walk_Loopsen rampant, tête à ~40 cm. - Prone sur place corrigé (se coucher sans bouger gardait l'idle debout) :
- chooser : lignes « Prone Idle » et « Prone Moving » en
Gait = MatchAny(la gait ne passait àPRONEque ~4 s après la stance → aucune base valide entre-temps) ; Get_MMInterruptMode(ABP) : la branche GASP d'origine « (état de mouvement OU gait en mouvement OU stance changés) ET au sol » était débranchée ; rebranchée sur une 4e entrée du OR final (BlueprintTools.add_node_pin+connect_pins).- Vérifié via
ToggleProne: couché sur place (tête 40 cm), reptation 1,25 m/s, retour debout. - Reste : la touche C (maintien) déclenche le prone de façon irrégulière, partagée avec crouch.
- chooser : lignes « Prone Idle » et « Prone Moving » en
- Non testés par script, à vérifier à la main : cover AST (touche A), interactions (porte, placard, levier, pousser), nage, arc, mort.
- OK :
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_CMCest supprimé au nettoyage final (non converti).- Les 17 os manquants sont ajoutés au MetaHuman (
SKM_test_BodyMesh+metahuman_base_skel).