Maillage statique rattache au squelette Genesis 8 (os head), ajuste a la tete de Bridget, materiaux DazHair ; declaree par lp_Revival/Hairstyles/pocolov17.lphair. Attribution CC BY 4.0 dans Licenses/Free_3D_Models_Credits.txt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 KiB
11 — Audit d'optimisation UE 5.5 (lot O0)
Chantier ouvert le 2026-10-02, après la migration (V1.1). Objectifs fixés par l'utilisateur : ressources obsolètes ou gourmandes, goulots d'étranglement, organisation des dossiers, optimisations propres à UE5, suppression du superflu, outils et exemples Fab. Ce document est le lot O0 : mesures en lecture seule, aucune modification du projet. Les lots O1 et suivants (§6) suivent
10_Protocole_Operations.md.
1. Méthode et outils
| Mesure | Outil | Résultat |
|---|---|---|
| Inventaire des 8 563 assets (classe, taille, tags, références) sans chargement | Tools/AuditAssets.py (registre d'assets, exécuté par -run=pythonscript) |
Saved/Audit/assets.jsonl |
| Noms d'assets cités par les données et les Blueprints | croisement avec le texte de Content/Modules et les tables de noms de BPs, UI, Scenes |
Saved/Audit/candidats_jamais_nommes.json |
| Composition du build livré | build Shipping V1.1 (LifePlay_Build_5.5_Shipping) |
§3 |
| Performances en jeu | profileur CSV + suivi mémoire LLM : LifePlay_profil_O0.bat (build L7cdj) |
à faire par l'utilisateur (§5) |
Contrainte découverte, déterminante pour toute suppression ou réorganisation : le jeu désigne la
plupart des assets par leur nom court (Clothes4.txt, .lpworld, .lpcharacter), et les retrouve
en parcourant le registre par classe (GetAssetsByClass). Un asset sans référence dans le registre
peut donc être utilisé en jeu. Seules 5 lignes de données citent un chemin /Game/ complet (lunettes
de New3/Clothes).
2. Contenu du projet (6,44 Go, 24 912 fichiers)
| Classe | Nombre | Taille source | Constat |
|---|---|---|---|
SkeletalMesh |
1 057 | 4,08 Go | 100 % à un seul LOD ; 54 536 morph targets au total |
AnimSequence |
1 705 | 819 Mo | New2/Anims2 481, New3/Anims 418, New2/Daily 344, Daz/Anims 313 |
Texture2D |
2 969 | 810 Mo | majoritairement ≤ 1024 ; 68 en 2K/4K (visages, corps) |
SoundWave |
419 | 208 Mo | presque tous dans New2 |
MaterialInstanceConstant |
1 180 | 132 Mo | — |
StaticMesh |
650 | 128 Mo | 637 à un seul LOD ; fnt_decor14 180 000 triangles |
| Blueprints, widgets | 100 | 116 Mo | GI 50 Mo, Person 20 Mo |
Répartition des maillages squelettiques :
| Dossier | Maillages | Taille | Morph targets |
|---|---|---|---|
Heavy/Clothes4 (vêtements) |
940 | 2,43 Go | 45 936 (≈ 49 par vêtement) |
Heavy/Daz (corps, cheveux) |
22 | 633 Mo | 5 257 (bridget_gp : 1 070, 132 Mo) |
Heavy/New2 |
44 | 543 Mo | 1 570 |
Heavy/New3 |
36 | 360 Mo | 1 675 |
Heavy/New4 |
15 | 113 Mo | 98 |
Les vêtements portent chacun une copie des morphs du corps pour suivre la morphologie : c'est le premier poste de taille, et un coût par personnage à l'exécution (§4).
Textures :
- 835 textures non streamées (
NeverStream) et 794 sans mipmaps, dont 541 icônes deNew3/UI(normal pour de l'interface). - Le reste concerne des textures 3D (
Clothes4/Materials43,New2/Furniture41,Daz/Michael34,New4/Hairs17,New2/Beasts13) : sans mipmaps, elles scintillent à distance et occupent toujours leur pleine résolution en mémoire vidéo. - Toutes les textures sont dans le groupe
World, y compris l'interface ; seules 37 sont en compression normal map.
3. Build livré (Shipping V1.1 : 3,17 Go)
| Poste | Taille | Constat |
|---|---|---|
LifePlay/Content/Heavy (cuit) |
2,50 Go | paquets non compressés (bCompressed=False, pas de pak) |
LifePlay-Win64-Shipping.pdb |
207 Mo | symboles de débogage livrés par erreur (inutiles au joueur) |
LifePlay-Win64-Shipping.exe |
140 Mo | inclut tous les plugins moteur activés |
Engine/Plugins/NNE (débruiteur IA, ONNX Runtime) |
119 Mo | inutilisé par LifePlay ; activé par défaut par le moteur |
DirectML.dll, d3d12SDKLayers.dll |
19 Mo | DirectML : dépendance de NNE ; SDK Layers : couche de débogage D3D12 |
Engine/Plugins/Interchange |
12 Mo | import d'assets, inutile en jeu |
LifePlay/Content/Movies |
79 Mo | vidéo d'intro |
LifePlay/Content/Modules |
14 Mo | données texte (doivent rester en fichiers nus) |
Plugins moteur présents dans le build sans usage connu en jeu : NNE, Interchange, Fab, Bridge,
SpeedTreeImporter, MovieRenderPipeline, Paper2D, USDCore, HairStrands… Plusieurs viennent des
dépendances de McpAutomationBridge (outil d'éditeur, ERR-024) ou de l'activation par défaut du moteur.
4. Goulots probables (à confirmer par la mesure du §5)
| # | Hypothèse | Indice | Mesure qui tranchera |
|---|---|---|---|
| G1 | Coût CPU des personnages : jusqu'à des centaines de PNJ générés, chacun avec corps, cheveux et vêtements à morphs, animés à chaque image même hors champ | 339 personnages générés en 2 h (V1) ; aucun LOD, aucune optimisation de fréquence d'animation | temps du thread de jeu et d'animation (CSV) selon le nombre de PNJ visibles |
| G2 | Morph targets : 45 936 sur les vêtements, recalculés pour chaque personnage | bridget_gp 1 070 morphs |
temps GPU/CPU de déformation, mémoire Meshes (LLM) |
| G3 | Tick des Blueprints GI et Person (interpréteur du DSL, IA) |
606 fonctions dans GI |
temps du thread de jeu hors animation |
| G4 | Mémoire vidéo : textures non streamées et maillages sans LOD | §2 | LLM Textures, Meshes |
| G5 | Temps de chargement : 2,5 Go de paquets non compressés, chargés par chemin | build Shipping | durée du démarrage et des changements de lieu (journal) |
5. Mesure en jeu à réaliser
Dans D:\Game\LifePlay_Build_5.5_L7cdj\Windows, lancer LifePlay_profil_O0.bat (et non
LifePlay.exe) puis jouer environ 15 minutes :
- charger une partie avancée (nombreux contacts), rester 2 minutes sur la carte de la ville ;
- un lieu intérieur peuplé, 2 minutes ;
- un lieu extérieur peuplé (parc, plage), 2 minutes ;
- une scène avec plusieurs personnages ;
- quitter normalement.
Résultats : Windows\LifePlay\Saved\Profiling\CSV\*.csv (temps par image, thread de jeu, rendu, GPU,
par tranche de 9 000 images) et Saved\Profiling\LLM\*.csv (mémoire par catégorie). Ils serviront de
référence : chaque lot O1+ sera mesuré à l'identique, avant et après.
6. Leviers classés et lots proposés
| Lot | Levier | Gain attendu | Risque | Changement de comportement |
|---|---|---|---|---|
| O1 | Build : désactiver les plugins moteur inutiles au jeu (NNE, Interchange, Fab, Bridge…), ne plus livrer le .pdb ni les couches de débogage D3D12 |
≈ 350 Mo sur 3,17 Go, exécutable plus petit, démarrage plus court | faible (vérifier que ControlRig, IKRig, HairStrands ne sont pas utilisés par les assets) |
aucun |
| O2 | Paquets compressés (IoStore + Oodle) pour Content, Modules restant en fichiers nus |
taille du jeu et temps de chargement (à mesurer : souvent −30 à −50 %) | moyen : la version de l'auteur était en fichiers nus ; vérifier que les mods n'ajoutent que du texte | aucun pour le joueur |
| O3 | Fréquence d'animation des PNJ : VisibilityBasedAnimTickOption (pas d'animation hors champ), optimisation de fréquence (URO), voire Animation Budget Allocator. Appliqué par un sous-système C++, sans modifier Person |
thread de jeu (G1), proportionnel au nombre de PNJ | faible | PNJ hors champ figés (invisible au joueur) |
| O4 | Textures 3D sans mipmaps (≈ 130) : génération des mipmaps et streaming ; textures d'interface dans le groupe UI |
mémoire vidéo, scintillement à distance | faible | rendu plus net à distance |
| O5 | LOD des maillages squelettiques (corps, cheveux, vêtements) par la réduction intégrée d'UE5 | GPU et mémoire avec beaucoup de PNJ | moyen : les morphs doivent suivre sur les LOD ; contrôle visuel | légère simplification à distance |
| O6 | Morph targets inutilisés des vêtements : retirer ceux qu'aucune donnée ni aucun Blueprint ne pilote | taille (2,4 Go de vêtements) et coût de déformation | élevé : il faut la liste exacte des morphs pilotés (.lpcharacter, MorphTags, Person) |
aucun si la liste est exacte |
| O7 | Organisation : déplacer les sauvegardes de développement de Content/Saves (14 125 fichiers, 239 parties, non versionnées) hors du projet ; plan de nommage des dossiers Heavy/New, New2… |
lisibilité, éditeur plus rapide à indexer | les déplacements d'assets demandent des redirecteurs et un contrôle des 5 chemins /Game/ des données |
aucun |
| O8 | Supprimer les 258 assets jamais nommés ni référencés (animations Daz/Anims, icônes New3/UI…) |
60 Mo seulement (1 %) | moyen : un nom peut être construit par concaténation dans un Blueprint | aucun si l'analyse est juste |
Conclusion de l'audit statique : supprimer des assets rapporte peu (O8). Les vrais gains de taille sont dans le build (O1, O2) et dans les morphs des vêtements (O6). Les gains de fluidité sont dans l'animation et la déformation des personnages (O3, O5, O6), à confirmer par la mesure du §5.
Ordre recommandé : O1 (sans risque, gain immédiat), puis mesure §5, puis O3 et O4, puis O2, O5, O6 selon les résultats ; O7 et O8 en dernier.
7. Fonctions UE5 utiles, déjà dans le moteur
| Fonction | Usage pour LifePlay |
|---|---|
| Unreal Insights, profileur CSV, LLM | mesure (§5) |
| Size Map, Asset Audit, Reference Viewer (éditeur) | vérifier les dépendances avant O1, O7, O8 |
| Réduction de maillage squelettique intégrée | LOD des personnages (O5) |
Animation Budget Allocator (plugin moteur), URO, VisibilityBasedAnimTickOption |
coût d'animation des PNJ (O3) |
| Significance Manager (plugin moteur) | prioriser les PNJ proches |
| IoStore, compression Oodle | taille et chargement (O2) |
| Texture streaming, groupes de LOD de texture | mémoire vidéo (O4) |
Nanite ne s'applique pas aux personnages en 5.5 dans un cadre stable (maillages squelettiques) ; les
maillages statiques de LifePlay sont légers, sauf CentralLondon (1,08 million de triangles) et
fnt_decor14 : Nanite pourrait être évalué pour ces deux-là seulement.
8. Fab
Recherche publique « optimization » (2026-10-02, sans connexion) : la plupart des outils sont payants (10 à 150 €) et génériques. Ils reprennent pour l'essentiel les fonctions du §7 : optimisation du tick, Significance, outils de mesure, instanciation. Candidats à examiner, au choix de l'utilisateur :
- gratuits : Ultimate Optimization Toolkit (IchiQ), Optimization Tools plugin (Creative Elicya) ;
- adaptés aux nombreux PNJ : Significance Optimizer (MateoPlugins), Flex Significance (GameRec Studios), Open World NPC Optimization (Sergio Cavalli) ;
- gestion des assets : Project Optimization Toolkit (Leartes Tools).
Règles :
- l'ajout d'un produit à la bibliothèque Fab se fait par l'utilisateur, avec son compte ;
- tout plugin tiers est évalué dans une copie du projet, jamais livré sans lot dédié ;
- il ne doit jamais devenir une dépendance du build sans accord.
Recommandation : commencer par les fonctions du moteur (§7), qui couvrent les besoins identifiés sans dépendance nouvelle.
9. Résultats de la mesure en jeu (2026-10-02)
Build L7cdj (Development), LifePlay_profil_O0.bat, ≈ 12 minutes de jeu sur une machine AMD Ryzen 7 5800H avec carte graphique Radeon :
4 tranches complètes de 9 000 images (36 004 images). Données archivées dans
D:\Game\LifePlay_Backup_5.5\O0_profil_20261002, journal Saved/Logs/portage/O0_profil_20261002.log.
Lancement : la capture CSV doit être démarrée par
-ExecCmds="csvprofile repeat=20, csvprofile frames=9000". L'option-csvCaptureFramessur la ligne de commande démarre la capture avant l'initialisation du rendu, et le moteur s'arrête (IsRayTracingAllowed() may only be called once RHI is initialized).
9.1 Régime normal : aucun goulot
| Mesure (médiane par tranche) | Valeur |
|---|---|
| Temps d'image | 16,7 ms : le jeu est plafonné à 60 images/s et tient ce plafond |
| Thread de jeu | 3,9 à 4,4 ms |
| Thread de rendu | 7,8 à 8,5 ms (dont ≈ 9 ms d'attente, EventWait) |
| GPU | 7,3 à 11,1 ms |
Il reste environ deux fois de marge sur chaque thread. Les hypothèses G1, G2 et G4 (§4) ne se vérifient pas en régime normal sur cette machine.
9.2 Le vrai problème : les à-coups du thread de jeu
| Seuil | Images concernées (sur 36 004) |
|---|---|
| > 33 ms | 262 |
| > 50 ms | 159 |
| > 100 ms | 112 |
| > 250 ms | 43 |
| > 1 s | 3 (chargement de partie : 31,5 s ; application des réglages : 5,4 s ; 1,7 s) |
- Les images longues durent de 0,5 à 0,9 s, à intervalles irréguliers, plusieurs fois par minute ; le thread de jeu en est la cause, le rendu restant à 8 ms.
- Dans ces images, le temps va aux minuteries Blueprint (
TimerManager, 38 s cumulées) et aux nœudsDelay(FlushLatentActions, 9 s cumulées). - Ce sont les traitements de
GIdéclenchés par minuterie : passage du temps, IA, recherche de scènes, génération de personnages avec lecture de fichiers texte et chargement synchrone de maillages.
Nouvelle priorité : G6, à-coups des traitements Blueprint sur minuterie. Le CSV ne nomme pas les
fonctions Blueprint. L'étape suivante est une trace Unreal Insights avec les événements nommés
(-trace=cpu,frame,loadtime -statnamedevents), pour identifier les fonctions de GI en cause et les
chargements synchrones.
9.3 Mémoire (fin de session, LLM)
| Catégorie | Mo |
|---|---|
| Total processus | 3 546 |
| Textures | 624 |
| Physique (Chaos) | 463, dont 124 de structures d'accélération et 92 de maillages de collision (trimesh) |
| UObject | 226 |
| Cibles de rendu | 215 |
| Maillages | 75 |
La physique occupe presque autant que les textures. Hypothèse : collisions détaillées du maillage de la
ville (CentralLondon, 1,08 million de triangles) et des meubles. Ce poste devient le levier mémoire n° 1.
9.4 Lots révisés
| Ordre | Lot | Justification |
|---|---|---|
| 1 | O1 build (plugins, .pdb) |
inchangé : gain sûr de ≈ 350 Mo |
| 2 | O9 (nouveau) : trace Insights des à-coups, puis correction ciblée (chargement asynchrone, étalement des traitements) | seul défaut ressenti en jeu |
| 3 | O10 (nouveau) : collisions (ville et meubles) | 463 Mo de physique |
| 4 | O4 textures, O2 compression | mémoire vidéo, taille |
| — | O3, O5, O6 (animation, LOD, morphs) | reportés : aucun goulot mesuré en régime normal ; à remesurer sur une machine plus modeste |
10. Bibliothèque Fab de l'utilisateur (lue le 2026-10-02 sur fab.com)
La bibliothèque compte environ 3 000 produits, dont 302 outils et plugins. Produits utiles au chantier, déjà possédés :
| Produit | Éditeur | Intérêt pour LifePlay |
|---|---|---|
| Ultimate Optimization Toolkit | IchiQ | mesure et débogage des performances (O9) |
| Optimization Tools plugin | Creative Elicya | outils d'optimisation de niveau |
| Asset Analytics | Mohsen Tabasi | analyse du poids et de l'usage des assets (O7, O8) |
| Dash — Advanced Asset Manager | Polygonflow | gestion et recherche d'assets (O7) |
| Assets Auto Organizer | Beta Projects | réorganisation des dossiers (O7) : à n'utiliser qu'avec redirecteurs et vérification, le jeu cherchant les assets par nom |
| Asset Naming Convention Keeper ; Asset Sanitizer | Tobosoksini Games ; MallHockE | conventions de nommage (O7) |
| Ultimate UE5 Project Organizer | Iron Cauldron | modèle d'arborescence (O7) |
| MetaHuman Crowd Sample | Epic Games | exemple officiel de foule optimisée (budget d'animation, LOD) : référence pour O3/O5 |
| AssetDump: Agents-readable assets | fallingsappy | export lisible des assets pour un agent : pourrait compléter AuditAssets.py |
Ajouts du 2026-10-02 (4 outils) : UNOMi (synchronisation labiale par IA, service en ligne avec compte), Crimson Object
Pool (réutilisation d'acteurs au lieu de les créer et détruire), Crimson Input, Crimson Interaction. Tous ne
déclarent qu'UE 5.8 : ils sont distribués compilés pour cette version et sont inutilisables tels quels en 5.5. L'idée
de Crimson Object Pool est déjà appliquée par LifePlay, qui garde une réserve de personnages pré-créés
(DummyPersons, SpawnDummy).
Rien n'a été acheté, réclamé ni téléchargé. Chaque outil retenu sera évalué dans une copie du projet, dans un lot dédié, avec l'accord de l'utilisateur.
11. Lot O1 : build allégé (2026-10-02)
| Modification | Fichier |
|---|---|
20 plugins moteur limités à l'éditeur ("TargetAllowList": ["Editor"]) : NNEDenoiser, NNERuntimeORT, Interchange, InterchangeAssets, InterchangeTests, Fab, Bridge, MetaHumanSDK, SpeedTreeImporter, HairStrands, MovieRenderPipeline, Paper2D, USDCore, ChaosVD, LiveLink, ConcertMain, ConcertSyncClient, ConcertSyncCore, Takes, PythonScriptPlugin |
LifePlay.uproject |
Leur contenu n'est plus cuit (+DirectoriesToNeverCook) : sans cela, la cuisson échoue sur les pipelines Interchange |
Config/DefaultGame.ini |
Build sans symboles de débogage (-nodebuginfo) |
commande de build |
Justification : Tools/AuditScriptDeps.py (dépendances des 8 563 assets, lecture seule) montre que le contenu n'utilise
que 24 modules de code, dont aucun des plugins retirés. L'éditeur et l'outil MCP les gardent.
Piège : la cuisson incrémentale (-iterate) garde le contenu déjà cuit des plugins retirés ; il a été déplacé vers
D:\Game\LifePlay_Backup_5.5\O1\_cuisson_retiree.
| Build Shipping | Avant (V1.1) | Après (O1) |
|---|---|---|
| Taille | 3 246 Mo | 2 859 Mo (−387 Mo, −12 %) |
| Fichiers | 24 249 | 23 901 |
| Paquets du jeu | 8 561 | 8 561 |
NNE, Interchange, .pdb, DirectML.dll |
présents | absents |
Build : D:\Game\LifePlay_Build_5.5_O1. Validé en jeu le 2026-10-02 (« pas de soucis rencontrés »), tag O1-valide.
12. Lot O9 : trace Unreal Insights (2026-10-02)
Trace courte (≈ 4 min, 841 Mo, -trace=cpu,frame,bookmark,loadtime -statnamedevents), analysée en ligne de commande :
UnrealInsights.exe -OpenTraceFile=… -AutoQuit -NoUI -ExecOnAnalysisCompleteCmd="@=export.rsp" avec
TimingInsights.ExportTimerStatistics … -threads=GameThread. Résultats : D:\Game\LifePlay_Backup_5.5\O9.
Pièges : chemins avec
/(les\sont lus comme des échappements) ; une trace de 10 minutes (3,3 Go) demande plus de 50 Go de mémoire à l'analyse, et Insights s'arrête quand on ferme son avertissement de mémoire.
Constat principal : le chargement d'une partie (« Continue ») prend 71 s, dont :
| Fonction (thread de jeu) | Durée | Détail |
|---|---|---|
PC.AutoLoad → GI.loadgame |
60,8 s | — |
MapMarkers.SpawnMapMarkers (3 appels) |
59,9 s | MoveCity 29,4 s ; ActualSpawnMarkers 29,2 s |
MapMarkers.GenerateTrees / GenerateHISM |
28,8 s | — |
HISMC_AddInstance |
54,8 s pour 160 916 appels | arbres de la carte ajoutés un par un |
FChaosScene::AddActorsToScene, Init Body |
161 272 appels | un corps physique par arbre |
TickAsyncLoading GT (chargements bloquants) |
19,8 s | dont 10,5 s pour l'instance de jeu au démarrage |
LoadTxt |
8,0 s pour 1 413 appels | lecture des fichiers texte, répartie dans la partie |
Cause : les composants Tree et Car de MapMarkers (HierarchicalInstancedStaticMeshComponent) gardent la
collision par défaut (BlockAll). Chaque arbre de la carte (≈ 160 000) reçoit donc un corps physique Chaos. Cela
explique probablement aussi la physique à 463 Mo mesurée en §9.3. En jeu, hors chargement, le thread de jeu reste
léger : il est inactif la moitié du temps (Game thread idle time).
Pistes, par ordre de risque :
- Couper la collision des arbres et des voitures de la carte (
NoCollision) : chargement et mémoire fortement réduits. Cela change le comportement si le joueur doit être bloqué par les arbres sur la carte de la ville (à confirmer par l'utilisateur). - Garder la collision, mais ne la créer qu'une fois tous les arbres ajoutés (sous-système C++ : collision coupée
pendant
GenerateTrees, puis rétablie). Le gain porte sur le temps seulement, pas sur la mémoire.
Question préalable (protocole §3.1) : le chargement d'une partie prend-il aussi environ une minute en 4.27 ?
12.1 Correction appliquée et résultat (option 1, décision utilisateur)
Commandlet LPSetComponentCollision : composants Tree et Car de MapMarkers en NoCollision (CHG-062). Diff
LPDumpAssets avant/après : 2 lignes. Les composants HISM_C des bâtiments, ajoutés à la volée, gardent leur
collision. Build LifePlay_Build_5.5_O9, validé en jeu le 2026-10-02 : chargement plus court, arbres et voitures
toujours affichés. Tag O9-valide.
| Mesure (trace Insights et LLM) | Avant | Après |
|---|---|---|
| Bouton « Continue » jusqu'à la partie jouable | 71,1 s | 22,5 s (−68 %) |
GenerateTrees (par appel) |
15,4 s | 0,3 s |
Chargements bloquants (TickAsyncLoading GT, plus long) |
10,5 s | 1,3 s |
| Mémoire physique (Chaos) | 463 Mo | 313 Mo (−150 Mo) |
| Mémoire totale du processus | 3 546 Mo | 3 324 Mo |
Les deux sessions ont des durées différentes : les chiffres de mémoire sont indicatifs ; les durées de fonctions sont directement comparables.
Reste : ActualSpawnMarkers prend encore 15 s. Il ajoute ≈ 80 000 instances aux composants HISM_C des bâtiments,
avec ≈ 49 500 corps physiques. Une piste O9b serait d'en couper la collision, si elle ne sert pas aux clics (à vérifier).
12.2 Lot O9b : marqueurs de bâtiments (2026-10-02)
Les clics se font sur les icônes, pas sur les bâtiments (utilisateur). Les modèles NODE_AddHISM-0 et -1 (HISM_C)
de MapMarkers sont passés en NoCollision (CHG-063, diff : 2 lignes). Build LifePlay_Build_5.5_O9b, validé en jeu
le 2026-10-02 : icônes cliquables, affichage inchangé. Tag O9b-valide.
| Mesure | Origine (4.27 = 5.5) | Après O9 | Après O9b |
|---|---|---|---|
| « Continue » jusqu'à la partie jouable | 71,1 s | 22,5 s | 14,7 s (−79 %) |
ActualSpawnMarkers |
15,0 s | 15,1 s | 1,2 s |
HISMC_AddInstance (≈ 80 000 appels) |
— | 13,4 s | < 0,1 s |
| Corps physiques créés au chargement | 161 272 | 49 557 | 530 |
| Mémoire physique | 463 Mo | 313 Mo | 83 Mo (−82 %) |
| Mémoire totale du processus | 3 546 Mo | 3 324 Mo | 3 112 Mo |
Le levier O10 (§9.4, collisions de la ville) est ainsi largement traité : il ne reste que 83 Mo de physique.
13. Lot O2 : contenu compressé (IoStore + Oodle) (2026-10-02)
Retour aux réglages par défaut d'UE5, que le projet désactivait : UsePakFile=True, bUseIoStore=True,
bCompressed=True (Oodle Kraken). Modules (DirectoriesToAlwaysStageAsNonUFS) et Movies restent en fichiers nus.
Le jeu lit ses données texte et ses images externes directement sur le disque (ModdingExtra, LPVictoryCompat) : ces
lectures ne sont pas concernées (CHG-064).
| Mesure (build Development) | Fichiers nus (O9b) | Compressé (O2) |
|---|---|---|
| Taille du build | 3 367 Mo | 2 002 Mo (−40 %) |
| Nombre de fichiers | 23 928 | 2 104 |
| Contenu cuit | 2,5 Go (≈ 21 000 fichiers) | 1,24 Go (5 fichiers) |
| « Continue » jusqu'à la partie jouable | 14,7 s | 15,9 s (écart dans le bruit des sessions) |
Chargements bloquants (Flush Async Loading GT) |
6,0 s | 1,7 s |
| Initialisation de l'instance de jeu | 1,4 s | 0,7 s |
| Mémoire totale | 3 112 Mo | 3 255 Mo (sessions différentes) |
Validé en jeu le 2026-10-02 (7 contrôles) : vidéo d'introduction, liste des mods, chargement de partie, personnages et
scène, sauvegarde et rechargement, image externe, fermeture normale. Tag O2-valide.
Le gain porte sur la taille et le nombre de fichiers ; le temps de chargement reste du même ordre.
Décision (utilisateur, 2026-10-02) : la compression est conservée.
- Les mods sont tous des modules listés dans le jeu, sous
Modules. - Vérification : les 17 dossiers de
Content/Modulesne contiennent que du texte (.lpscene,.lpaction,.lpcharacter,.lpworld,.txt…) et 20 images.jpg, aucun.uasset. Ils restent en fichiers nus et ne sont donc pas concernés. - Un mod qui remplacerait des
.uassetdeContentne fonctionnerait plus. Si un tel mod apparaît, il faudra prévoir une variante de distribution en fichiers nus.
14. Lot O4 : mipmaps des textures 3D (2026-10-02)
Tools/FixTextureMips.py (CHG-065) retient les textures sans mipmaps ou non streamées qui remplissent toutes ces conditions :
- dimensions en puissance de 2 ;
- référencées par au moins un matériau, et par aucun widget ni Blueprint ;
- ni cheveux, ni masques de transparence (les mipmaps amincissent mèches et découpes à distance).
29 textures sont retenues : 27 de vêtements (Clothes4), la route et le trottoir de la carte. Sont écartées : 733 aux
dimensions non standard (surtout des icônes), 44 d'interface ou chargées par nom, et 29 de cheveux ou de transparence.
Le diff ne porte que sur MipGenSettings, NeverStream et LightingGuid (régénéré).
Validé en jeu le 2026-10-02 (« la build semble bonne »), tag O4-valide. Gain surtout visuel (scintillement à distance) ;
gain mémoire faible, ces textures étant petites.
Conclusion du levier « textures » : l'essentiel des 835 textures non streamées est fait d'icônes d'interface, pour lesquelles c'est le bon réglage. Aucun autre lot de textures n'est justifié.
15. Build Shipping de distribution (O1 + O2 + O4 + O9 + O9b) (2026-10-02)
Commande : BuildCookRun … -clientconfig=Shipping -build -cook -iterate -stage -pak -iostore -compressed -archive -archivedirectory=D:\Game\LifePlay_Build_5.5_Shipping_V1.2 -nodebuginfo. Cuisson : 0 erreur, 0 avertissement.
| Build Shipping | V1.1 (fichiers nus) | Optimisé |
|---|---|---|
| Taille | 3 246 Mo | 1 494 Mo (−54 %) |
| Fichiers | 24 249 | 2 084 |
| Exécutable et DLL | 375 Mo (dont .pdb 207 Mo) |
145 Mo |
Contenu (Paks, Modules, Movies) |
≈ 2,6 Go | 1,33 Go |
| Moteur | ≈ 270 Mo (dont NNE 119 Mo) |
13 Mo |
Disposition : LifePlay.exe, LifePlay/Binaries, LifePlay/Content/{Paks, Modules, Movies}, Engine (10 fichiers).
Premier essai : aucune ville proposée en nouvelle partie. UI/CityMenu listait les fichiers Heavy/StreetMap/*.uasset
sur le disque, absents avec IoStore. Le build Development d'O2 avait le même défaut : le test, passé par « Continue »,
n'ouvrait pas ce menu. Correction O2b (CHG-067) dans ModdingExtra::GetAllFilesFromFolder : repli sur le registre
d'assets quand le disque ne renvoie aucun paquet. Build reconstruit, validé en jeu le 2026-10-02 (« fonctionne comme
attendu »), tag O2b-valide.
Leçon (reportée dans 10_Protocole_Operations.md §4) : un changement de packaging se teste aussi en nouvelle partie
(choix de ville, création de personnage), pas seulement par « Continue ».
16. Lot O7 : réorganisation des dossiers — audit (2026-10-02, lecture seule)
16.1 Carte de Content/Heavy (6,2 Go)
| Dossier | Taille | Contenu principal | Sous-dossiers |
|---|---|---|---|
Clothes4 |
2 705 Mo | vêtements : 940 maillages, 996 textures, 883 matériaux | Materials |
New2 |
1 359 Mo | meubles, animations, sons, cheveux | Furniture 803, Anims2 481, Sound 418, Daily 344, Hairs 243, BDSM, Beasts, Buildings |
Daz |
1 054 Mo | corps Bridget et Michael, animations, vêtements | Anims 314, Bridget 180, Michael 113, Clothes 52 |
New3 |
695 Mo | icônes, animations, cheveux, tatouages | UI 555, Anims 443, Hairs 225, Tattoos 71, Characters… |
New4 |
239 Mo | animations, cheveux | Anims 145, Hairs 118, Misc, Tentacles |
Backgrounds |
82 Mo | 80 images de fond | — |
StreetMap |
79 Mo | 280 villes et leurs 280 maillages | Static |
Characters, New, New5 |
7 Mo | divers (squelette, 37 icônes, 1 animation) | — |
16.2 Contrainte : des chemins de dossiers font partie du fonctionnement du jeu
Les références directes entre assets sont mises à jour par l'éditeur lors d'un déplacement (redirecteurs). En revanche, 10 préfixes de dossiers sont écrits en texte dans les Blueprints, et le jeu y ajoute un nom lu dans les données :
| Préfixe | Blueprint | Usage |
|---|---|---|
/Game/Heavy/New2/Furniture/ |
Room |
meubles des .lpworld (modules et mods) |
/Game/Heavy/Clothes4/ |
GI |
vêtements de Clothes4.txt |
/Game/Heavy/StreetMap/, …/StreetMap/Static/ |
GI |
villes |
Heavy/StreetMap (relatif) |
UI/CityMenu |
liste des villes |
/Game/Heavy/New3/Tattoos/ |
GI |
tatouages |
/Game/Heavy/New3/Characters/Tanlines/ |
Person |
marques de bronzage |
/Game/Heavy/Daz/Bridget/Hairs/Pubic/, /Game/Heavy/Daz/Michael/hairs/other/ |
GI, Person |
pilosité |
/Game/Heavy/New3/UI/ |
UI/VisualMorph |
icônes de morphs |
Heavy/Daz/Clothes/ (relatif) |
UI/Inventory_Cloth |
vêtements Daz |
S'y ajoutent 17 chemins complets dans Content/Modules (New2, New3). Les modules et les mods de la communauté
désignent meubles, vêtements et cheveux par leur nom, dans ces dossiers : leur emplacement fait partie du contrat
de modding.
16.3 Options
| Option | Contenu | Risque | Recommandation |
|---|---|---|---|
| O7a, ménage | Content/Saves (239 parties de test de l'éditeur, 85 Mo, non versionnées, non livrées) déplacées vers la sauvegarde ; dossiers vides Content/Developers et Content/Collections retirés ; 3 captures de diagnostic à la racine déplacées vers D:\Game\LifePlay_Backup_5.5 |
nul | oui |
| O7b, carte documentée | §16.1 et §16.2 portés dans 08_Guide_Developpeur.md : ce que contient chaque dossier, et quels dossiers ne doivent pas bouger |
nul | oui |
| O7c, renommage réel | renommer New, New2… par thème (Furniture, Animations, Hair…), corriger les 10 préfixes dans 6 Blueprints et les 17 chemins des données |
élevé : mods de la communauté cassés, comparaisons avec 4.27 perdues, des milliers de paquets réenregistrés | non (gain seulement cosmétique) |
16.4 Réalisé (2026-10-02)
- O7a :
Content/Savesvidé : 14 125 fichiers (239 parties de test) déplacés versD:\Game\LifePlay_Backup_5.5\O7\Content_Saves, nombre de fichiers et d'octets vérifiés identiques ; le dossier est conservé, vide ;Content/DevelopersetContent/Collectionsretirés : ils ne contenaient que des dossiers vides, que l'éditeur recrée ;- 3 captures de diagnostic de la racine rangées dans
D:\Game\LifePlay_Backup_5.5\O7\racine.
- O7b : carte des dossiers et liste des dossiers à ne pas déplacer dans
08_Guide_Developpeur.md§2.1.
Aucun asset déplacé, aucun Blueprint modifié : ni build ni test en jeu nécessaires.
16.5 O7d : collections thématiques (2026-10-02)
Pour retrouver les assets par thème sans renommer de dossier, Tools/BuildCollections.py crée 13 collections statiques
de l'éditeur (Saved/Collections/LifePlay*.collection), rangées sous une collection parente LifePlay :
| Collection | Assets | Contenu |
|---|---|---|
LifePlay_Animations |
1 709 | toutes les animations (Daz/Anims, New2/Anims2, New2/Daily, New3/Anims, New4/Anims…) |
LifePlay_Vetements |
2 926 | Clothes4 et ses matériaux, Daz/Clothes, New3/Clothes, New2/BDSM |
LifePlay_Meubles |
803 | New2/Furniture |
LifePlay_Cheveux |
776 | tous les dossiers Hairs (dont pilosité Daz) |
LifePlay_Icones_UI |
796 | icônes et fonds d'écran |
LifePlay_Villes |
594 | StreetMap et New2/Buildings |
LifePlay_Sons |
419 | sons |
LifePlay_Corps |
236 | corps Daz, squelettes, visages, créatures |
LifePlay_Gameplay |
169 | Blueprints, widgets, structures, carte, rendu |
LifePlay_Tatouages |
71 | New3/Tattoos |
LifePlay_Divers |
62 | Misc, particules, accessoires d'animation |
LifePlay_Chemins_Fixes (rouge) |
4 984 | transversale : assets des dossiers à chemin écrit en dur (§16.2), à ne jamais déplacer |
Chaque asset du projet (8 561, hors redirecteur et données de carte) est dans exactement une collection thématique. Les collections ne sont que des listes : aucun asset n'est modifié, rien n'est cuit ni livré dans le jeu. Elles ne sont ni versionnées ni archivées : le script est la source et les régénère à l'identique (GUID fixes).
Ce sont des collections locales (Saved/Collections). Une première version les écrivait en collections partagées
(Content/Collections) : l'éditeur associe toujours celles-ci au contrôle de révision, désactivé dans ce projet, et
affichait l'avertissement « Collection is missing its revision control provider » (constaté par l'utilisateur). Les
fichiers ont été déplacés vers D:\Game\LifePlay_Backup_5.5\O7d\Content_Collections et régénérés en local,
identiques à l'octet près. Contrôles : relecture des 13 fichiers, 13 545 chemins, 0 inconnu du registre ; l'éditeur les
charge (LogCollectionManager: Loaded 13 collections).
16.6 O7e : intégrer une coiffure de Fab — étude (2026-10-02, lecture seule)
Test d'intégration proposé par l'utilisateur : ajouter une coiffure de sa bibliothèque Fab. Relevés : LPDumpFunction
(GI, Person, UI/Hairstyle, tous graphes) et LPDumpCDO (GI_C).
Contrat d'une coiffure LifePlay
| Point | Constat |
|---|---|
| Liste des coiffures | GI.HairstyleTable : valeur par défaut du Blueprint (126 entrées), jamais construite par le jeu. Chaque entrée (SMBool) : chemin complet du maillage, Bool = coiffure masculine, Daz = coiffure Daz, Strings (zones de pilosité faciale). 88 entrées existent ; 35 coiffures d'avant Daz pointent vers des assets absents, déjà en 4.27, et ne sont jamais chargées (LegacyPercentage = 0). |
| Choix d'une coiffure | GenerateAndApplyStrings, catégorie Hairstyle : parcourt HairstyleTable et compare le nom de l'objet à la valeur lue (HAIR Hairstyle: ToulouseHR) ; tirage aléatoire parmi les entrées du bon sexe. Un maillage absent de la table n'est donc jamais utilisé, même désigné par nom. |
| Chargement | GI.LoadHairMeshIfNeeded : chargement à la demande depuis le chemin de la table. |
| Animation | Person.HairSM.SetLeaderPoseComponent(corps) : la coiffure suit le corps par noms d'os. Les coiffures existantes sont des SkeletalMesh à squelette propre de 20 à 27 os Genesis 8 (hip, pelvis, abdomenLower… neckUpper, head). |
| Forme | Person.FitMorphableHair (table GI.MorphableHairs) reporte les morphs du corps et du visage sur la coiffure (146 à 362 morphs par coiffure, ex. ToulouseHR__CTRLFitness). Sans ces morphs, la coiffure garde sa forme d'origine (risque de traverser une tête modifiée). |
| Couleur | paramètres de matériau HairColor et HairThickness (menu UI/Hairstyle, GI.GetHairThicknessAndColor). |
| Sauvegarde | les personnages (.lpcharacter) stockent la coiffure par nom : ajouter une entrée en fin de table ne change rien aux parties existantes. |
Bibliothèque Fab : 34 coiffures. Les « grooms » MetaHuman (≈ 18) sont exclus : liés à la tête MetaHuman, et le
plugin HairStrands n'est plus actif dans le jeu depuis O1. Restent ≈ 12 maillages FBX/OBJ (Pocolov Hair 05, 06, 16,
17 ; Laflian ; NoEdge ; Carlos-H). Pocolov publie des coiffures Daz ; le rig Genesis du FBX reste à constater.
Intégration proposée (O7e)
- Télécharger un produit (accord utilisateur), importer dans
/Game/Heavy/New5/Hairs/(hors chemins fixes). - Si le FBX n'est pas riggé Genesis 8 : le rattacher à une chaîne d'os Genesis (poids entier sur
head), squelette propre comme les coiffures existantes ; matériau enfant d'un matériau de cheveux existant (HairColor,HairThickness). - Ajouter une entrée en fin de
GI.HairstyleTablepar une commandlet dédiée (même méthode queLPSetComponentCollision: essai à blanc, contrôle, diffLPDumpCDOavant/après = 1 entrée). BuildCollections.py: la coiffure apparaît dansLifePlay_Cheveux.- Test en jeu : personnage
.lpcharacteravecHAIR Hairstyle: <nom>, menu de création, suivi des animations. Morphs de forme : hors périmètre du premier essai.
16.7 H1 : coiffures déclarées par fichiers .lphair (2026-10-02)
Demande utilisateur : une table figée dans un Blueprint ne se prête pas au modding ; externaliser la liste des
coiffures. Réalisation sans modifier de Blueprint : Source/LifePlay/LPHairstyleSubsystem (sous-système de
GameInstance).
Format : un fichier par coiffure, Modules/<module>/**/*.lphair :
HAIRSTYLE: /Game/Heavy/New5/Hairs/Exemple.Exemple
SEX: F (F ou M, défaut F)
DAZ: true (défaut true)
FIT_MORPH: Exemple__AllExpand 0.45 (facultatif)
Fonctionnement
- au démarrage, relevé des fichiers
.lphairdeModules; sans fichier, le sous-système ne fait rien ; - chaque coiffure d'un module actif (
GI.ModEnableds) est ajoutée en fin deGI.HairstyleTable; son morph d'ajustement éventuel est ajouté àGI.MorphableHairs; - contrôles : maillage présent dans le registre d'assets et de classe
SkeletalMesh, chemin absent de la table (pas de doublon) ; chaque refus est journalisé (LogLifePlay) ; - les entrées du Blueprint ne sont jamais modifiées ni réordonnées ; les personnages stockent la coiffure par nom : les sauvegardes restent compatibles ;
- la liste des modules actifs est relue toutes les 2 s : activer ou désactiver un module dans le gestionnaire ajoute ou retire ses coiffures (les entrées ajoutées sont retirées puis reconstruites).
Premier module : Modules/lp_Revival (lp_Revival.lpmod, désactivable), qui déclare la coiffure de test
/Game/Heavy/New5/Hairs/H1_TestHair : copie de New4/Hairs/FloraHair_New sous un nouveau nom, donc absente de la
table (à remplacer par une coiffure Fab, lot O7e). Les 88 coiffures présentes dans le projet sont toutes dans la table.
Vérifications (build LifePlay_Build_5.5_H1, journal du jeu) :
- doublons : deux fichiers d'essai désignant
soldieretarmani(déjà dans la table sousSoldier,Armani) sont refusés avec « déjà dans la table » ; la comparaison des chemins ignore la casse, comme les noms d'assets d'UE ; - ajout :
H1_TestHair ajoutee (index 126, F, module lp_Revival), table de 127 entrées ; - validé en jeu le 2026-10-02 : nouvelle partie (liste des villes), coiffure de test en fin de liste du menu de création, suivi des animations, module désactivé puis réactivé dans le gestionnaire (coiffure retirée puis rendue), Continue ;
- piège de build : avec
-iterate, la mise en place ne supprime pas les fichiers retirés deModules; un fichier supprimé doit l'être aussi du build (ou le build refait à neuf avant publication).
Limite : le maillage doit être importé dans le projet et cuit avec le jeu ; un mod ne peut pas encore apporter
son propre maillage (étape H3 : paquets .pak montés depuis Modules/<mod>/).
16.8 O7e : première coiffure Fab, Pocolov Hair 17 (2026-10-02)
Source : Pocolov Hair 17 (Pocolov Studio 2019, artiste Thang), bibliothèque Fab de l'utilisateur, pocolov-hair-17.zip
(1,4 Mo, FBX), licence CC BY 4.0 : attribution dans Licenses/Free_3D_Models_Credits.txt et dans le fichier .lphair.
Copie de l'archive et des assets d'import dans D:\Game\LifePlay_Backup_5.5\O7e.
Constat : maillage statique (Hair_17, 8 250 triangles) livré avec une tête de référence (Head) ; aucun os,
aucune pondération ; matériaux sans texture reliée. Blender absent de la machine.
Chaîne d'intégration (reproductible pour d'autres coiffures statiques) :
- import FBX en maillages statiques séparés (Python,
AssetImportTask) dans un dossier de travail ; - nouvelle commandlet
LPHairFromStaticMesh(Source/LifePlayEditorTools) :- mesure la tête de Bridget (
bridget_gp, 6 691 sommets rattachés àheadou à ses descendants : 18,1 × 22,5 cm) et la tête de référence (24,4 × 20,7 cm) ; - place la coiffure : échelle par axe (largeur 0,740, profondeur 1,088, hauteur 0,914), centre et sommet du crâne
alignés ; option
-Uniform, retouches-Scale,-OffsetZ,-OffsetY; - vérifie la pose de référence de l'os
head: identique entre le corps et le squelette cible (aucune correction) ; - convertit (
FStaticToSkeletalMeshConverterdu moteur) sur une copie du squelette deFloraHair_New(23 os Genesis 8), tous les sommets liés àhead; essai à blanc-DryRun;
- mesure la tête de Bridget (
- matériaux
Pocolov17_CapetPocolov17_Strands, enfants deDaz/Bridget/Hairs/DazHair(paramètres du jeuHairColor,HairThickness) :MapDiffuse= mèches grises,MapOpacity= lisière de la calotte / mèches ;Thicken1 et 10 comme Flora ; - dossier de travail retiré du projet (sauvegardé) ; dépendances contrôlées : la coiffure ne référence que son squelette et ses deux matériaux ;
- déclaration
Modules/lp_Revival/Hairstyles/pocolov17.lphair(H1) ; la coiffure de testH1_TestHairest retirée (sauvegardée).
Assets : Content/Heavy/New5/Hairs/Pocolov17 (+ _Skeleton, _Cap, _Strands, 3 textures ; ≈ 1,7 Mo). Build
LifePlay_Build_5.5_O7e : Pocolov17 ajoutee (index 126, F, module lp_Revival).
Limites connues : pas de morphs de forme (la coiffure ne suit pas les morphs du visage) ; rigide sur la tête (pas de mouvement des mèches) ; ajustement automatique à contrôler visuellement.
17. Couche de données : stratégie (2026-10-02)
Proposition utilisateur : convertir les fichiers texte de Modules en fichiers JSON groupés par type, avec un calque de
valeurs par défaut, chargés une seule fois, avec un sous-module pour ingérer l'ancien format (mods).
Retenu : le texte reste la source (jeu de base et mods), et le JSON devient la représentation compilée chargée en une fois. Cela évite deux sources de vérité, deux analyseurs à maintenir à l'identique, et une rupture avec le format connu des moddeurs.
| Étape | Contenu | Effort |
|---|---|---|
| 1 | mesure : temps de chargement des données et lectures par type | 1 lot |
| 2 | sous-système C++ : Modules lu une seule fois et gardé en mémoire ; LoadTxt servi depuis la mémoire |
1 lot |
| 3 | cache compilé par type (JSON ou binaire), régénéré quand les sources changent, avec calque de valeurs par défaut | 1 à 2 lots |
| 4 (facultatif) | analyseurs de GI réécrits en C++, format par format, vérifiés à l'identique |
1 lot par format |
Rappels :
Modulespèse 14 Mo : le gain porte sur le nombre de fichiers et le temps, pas sur la taille.- Les corps de
.lpscene/.lpaisont des scripts : un format JSON ne change rien à leur interprétation.
17.1 Étape 1 : premières mesures (trace O2, build Development)
Fonction (GI) |
Durée | Remarque |
|---|---|---|
PopulateRaws |
12,6 s par appel, 3 appels dans la session | lit et analyse tout Modules ; relancé à chaque chargement de partie |
LoadTxt |
7,4 s pour 2 705 lectures | 2,75 ms par fichier de quelques Ko : coût d'ouverture de fichier |
PopulateScenes |
3,6 s par appel | analyse des en-têtes de scènes |
PopulateActions |
1,9 s par appel | — |
PlayScene, LoadPreset en jeu |
0,2 s et 0,3 s au total | négligeable |
Au menu principal, seuls 11 fichiers sont lus (0,085 s) : la lecture de Modules a lieu au lancement d'une partie.
Instrumentation ajoutée à ModdingExtra::LoadTxt : bilan par type de fichier à la fermeture du jeu et par la commande
console ModdingExtra.LoadTxtStats (build LifePlay_Build_5.5_DATA1).
17.2 Étape 1 : résultats (2026-10-02)
Lancement d'une partie (« Continue ») sur le build DATA1, juste après sa construction (fichiers jamais lus) :
| Type | Lectures | Fichiers | Relectures | Volume | Temps de lecture |
|---|---|---|---|---|---|
.lpscene |
816 | 813 | 3 | 2,5 Mo | 3,86 s |
.lpaction |
305 | 305 | 0 | 113 Ko | 1,23 s |
.lpstat |
74 | 74 | 0 | 19 Ko | 0,33 s |
autres (.lpai, .lpworld, .txt, .lpcharacter…) |
96 | 59 | 37 | 0,9 Mo | 0,26 s |
| Total | 1 291 | 1 251 | 40 | 3,6 Mo | 5,7 s |
Comparaison hors du jeu, sur les 1 271 .lpscene : 2,4 ms par fichier à la première lecture, mais 0,11 ms par fichier
une fois le cache du système chaud. Le coût vient de l'ouverture à froid de centaines de petits fichiers (cache disque,
antivirus), pas de leur taille.
Cela se retrouve dans la trace O2 :
PopulateRawsprend 12,6 s au premier passage (fichiers froids), puis ≈ 6 s quand il est relancé (fermeture du gestionnaire de mods,CloseModManager6,2 s) ;- ≈ 6 s viennent donc de la lecture à froid et ≈ 6 s de l'analyse en Blueprint (
PopulateScenes3,6 s,PopulateActions1,9 s…), à chaque passage.
Conséquences pour la suite :
- Étapes 2 et 3, réunies (un fichier compilé lu une fois, puis
LoadTxtservi depuis la mémoire) : environ −5 à −6 s au premier chargement d'une partie, gain faible ensuite. - Étape 4 (analyse en C++) ou suppression des relances inutiles de
PopulateRaws: jusqu'à −6 s à chaque passage.
17.3 Étapes 2 et 3 : couche de données (2026-10-02)
Nouveau Plugins/ModdingExtra/Source/ModdingExtra/Private/LPDataCache.h/.cpp, lancé au démarrage du module (hors
commandlets) :
- relevé : date et taille des fichiers texte de
Modules(.lp*,.txt,.config,.cfg), sans ouverture ; - cache compilé : un JSON par type dans
Saved/LPDataCache/<type>.json(version,type,files). Pour chaque fichier :stamp,size,textet, pour.lpaction,.lpstat,.lpquest,.lpmod, desfields(champs « CLÉ: valeur » analysés). Le calque de valeurs par défaut, fichier optionnelContent/Modules/_lpdata_defaults.json, complète les champs absents des enregistrements ; - mise à jour incrémentale : seuls les fichiers nouveaux ou modifiés sont relus (mods ajoutés, éditions) ;
LoadTxtsert le texte depuis la mémoire, identique à la lecture du disque ;SaveTxtmet la mémoire à jour ; la lecture se fait sur le disque avant la fin du chargement, ou horsModules(sauvegardes) ;- options :
-LPNoDataCachepour désactiver,-LPDataCacheVerifypour comparer chaque texte servi au disque.
Mesure (build LifePlay_Build_5.5_DATA23, en arrière-plan au menu) |
Valeur |
|---|---|
| 1ᵉʳ lancement : construction du cache (2 051 fichiers, images comprises) | 12,3 s |
| Lancements suivants : chargement depuis le cache (2 031 fichiers texte) | 0,14 s |
| Relevé des dates et tailles | 0,014 s |
| Cache (11 fichiers JSON) | ≈ 8 Mo, dont lpscene 4,6 Mo |
Validé en jeu le 2026-10-02 (LifePlay_verif_cache.bat, -LPDataCacheVerify) : partie avec « Continue »,
scènes, changement de lieu, gestionnaire de mods.
- 2 658 textes servis par le cache, 0 écart avec la lecture du disque.
- Temps de lecture de toute la session : 0,074 s pour 2 690 lectures, contre 5,7 s pour un seul chargement de partie auparavant.
- Ce qui reste lu sur le disque est voulu :
.lpcharacterdes sauvegardes (Saves/_session), horsModules.
Tag DATA23-valide. Reste l'analyse en Blueprint (≈ 6 s par passage de PopulateRaws) : étape 4.
Constat annexe : 4 erreurs GroomComponent : Failed to find /HairStrands/Materials/… au démarrage depuis le lot O1. Le
module HairStrands reste intégré au jeu, car d'autres plugins en dépendent, alors que son contenu n'était plus cuit.
Correction ERR-039 (CHG-077) : /HairStrands retiré de DirectoriesToNeverCook (≈ 0,8 Mo). Plus aucune erreur au
démarrage.
17.4 Étape 4 : étude (2026-10-02, lecture seule)
Déclencheurs de PopulateRaws (EventGraph de GI, relevé avec LPDumpFunction -Exec) :
- l'événement
LoadSettings, au lancement d'une partie (« Continue » ou nouvelle partie) ; - l'événement de fermeture du gestionnaire de mods (
ShowUI→ClearModManagerWidget→PopulateRaws), même sans changement de mods.
Découpage d'un passage (trace O2, fenêtres temporelles des événements) :
| Phase | 1ᵉʳ passage (fichiers froids) | 2ᵉ passage (fichiers chauds) | Avec la couche de données |
|---|---|---|---|
Lecture des fichiers (LoadTxt…) |
7,0 s | 0,66 s | ≈ 0,07 s |
PopulateActions |
1,93 s | 1,84 s | inchangé |
PopulateScenes |
3,64 s | 3,59 s | inchangé |
Total PopulateRaws |
12,6 s | 6,1 s | ≈ 5,5 s |
Où passe le temps de l'analyse (statistiques limitées à la fenêtre de chaque événement) :
PopulateScenes: 94 % dans une seule fonction,WhatWhereToArray(3,43 s pour 1 558 appels, un par scène). Elle développe les listesWHAT:/WHERE:(par exempleall, -sleep, -nap) en parcourant pour chaque scène les tableaux de structuresActionDetailetAmenityAction. Cela fait 503 000 lectures d'éléments de tableau, chaque structure étant copiée par le Blueprint (2,18 s), et 1,27 million de comparaisons de texte (0,55 s).PopulateActions: boucle de l'EventGraph sur les lignes des actions. 473 000 lectures d'éléments (0,94 s), et ≈ 234 000 appels chacun àTrim,StartsWith,EndsWithet à des comparaisons (≈ 0,6 s).
Options :
| Option | Contenu | Gain par passage | Effort | Risque |
|---|---|---|---|---|
| 4a | ne plus relancer PopulateRaws à la fermeture du gestionnaire de mods si la liste des mods actifs est inchangée (branche ajoutée dans GI par commandlet, contrôle de diff) |
≈ 5,5 s à chaque fermeture sans changement | 1 lot | faible |
| 4b | WhatWhereToArray réécrite en C++ (LPDataCompat, même signature), nœuds rebranchés par commandlet comme les correctifs CX-B ; preuve d'équivalence : commandlet qui exécute les deux versions sur les 1 558 en-têtes et compare |
≈ 3,3 s à chaque passage | 1 à 2 lots | moyen (lecture des structures Blueprint par réflexion) |
| 4c | boucle de PopulateActions en C++ |
≈ 1,5 s | 1 à 2 lots | moyen (logique au milieu de l'EventGraph) |
| 4d | réécriture complète des analyseurs (étape 4 d'origine) | — | 10 à 15 lots | abandonnée : le coût est concentré dans 4b et 4c |
Ordre recommandé : 4b (le plus gros gain, à chaque chargement de partie), puis 4a, puis 4c si nécessaire. Chargement de données attendu après 4b et 4c : ≈ 0,7 s au lieu de 12,6 s au premier lancement.
17.5 Étape 4b : WhatWhereToArray en C++ — résultats (2026-10-02)
- Équivalence (
-LPVerifyWhatWhere, chaque appel compare la version C++ à la fonction Blueprint d'origine) : plus de 3 000 appels sur deux chargements complets (« Continue », puis fermeture du gestionnaire de mods), 0 écart. - Mesure (trace
DATA4b.utrace, avec la couche de données) :
| Fonction | Avant (trace O2) | Après 4b |
|---|---|---|
PopulateScenes |
3,6 s | 0,15 s |
PopulateActions |
1,9 s | 0,9 à 1,0 s |
PopulateRaws (chargement de partie) |
12,6 s (froid) / 6,1 s (chaud) | 1,26 s / 1,17 s |
WhatWhereToArray, 3 185 appels |
≈ 3,4 s par passage | 0,2 s au total |
Le chargement des données d'une partie est divisé par 10. Les avertissements LoadTxt ECHEC (OldPlayer.lpcharacter,
nom vide) existaient déjà avant ce lot (journaux O2, ERR038). Tag DATA4b-valide.
Reste PopulateActions (≈ 1 s, option 4c) et la relance à la fermeture du gestionnaire de mods (option 4a, ≈ 1,2 s
désormais) : gains devenus faibles.
18. Build Shipping V1.3 (2026-10-02)
BuildCookRun … -clientconfig=Shipping … -pak -iostore -compressed -nodebuginfo, sortie
D:\Game\LifePlay_Build_5.5_Shipping_V1.3. Cuisson : 0 erreur, 0 avertissement. 1 494 Mo, 2 084 fichiers (comme la V1.2).
Contenu par rapport à la V1.2 :
- couche de données (CHG-075, CHG-076) ;
WhatWhereToArrayen C++ (CHG-078) ;- contenu
HairStrandsde nouveau cuit (ERR-039, CHG-077) ; - retrait du sous-système ERR-038 (CHG-073 : aucun changement de comportement par rapport à la V1.2).
En Shipping, le dossier Saved est dans le profil de l'utilisateur, %LOCALAPPDATA%\LifePlay\Saved, comme les
sauvegardes .sav. Le cache s'y trouve donc dans LPDataCache. Lancement de contrôle jusqu'au menu : cache construit
(11 fichiers), aucun plantage. Validé en jeu le 2026-10-02 (nouvelle partie, Continue, scènes, gestionnaire de
mods, sauvegarde et rechargement, carte de la ville).