# 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 de `New3/UI` (normal pour de l'interface). - Le reste concerne des textures 3D (`Clothes4/Materials` 43, `New2/Furniture` 41, `Daz/Michael` 34, `New4/Hairs` 17, `New2/Beasts` 13) : 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** : 1. charger une partie avancée (nombreux contacts), rester 2 minutes sur la carte de la ville ; 2. un lieu intérieur peuplé, 2 minutes ; 3. un lieu extérieur peuplé (parc, plage), 2 minutes ; 4. une scène avec plusieurs personnages ; 5. 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 `-csvCaptureFrames` sur 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œuds `Delay` (`FlushLatentActions`, 9 s cumulées). - Ce sont les traitements de `GI` dé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 : 1. 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**). 2. 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/Modules` ne 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 `.uasset` de `Content` ne 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/Saves` vidé : 14 125 fichiers (239 parties de test) déplacés vers `D:\Game\LifePlay_Backup_5.5\O7\Content_Saves`, nombre de fichiers et d'octets vérifiés identiques ; le dossier est conservé, vide ; - `Content/Developers` et `Content/Collections` retiré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. ## 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 : - `Modules` pèse 14 Mo : le gain porte sur le nombre de fichiers et le temps, pas sur la taille. - Les corps de `.lpscene`/`.lpai` sont 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 : - `PopulateRaws` prend 12,6 s au premier passage (fichiers froids), puis ≈ 6 s quand il est relancé (fermeture du gestionnaire de mods, `CloseModManager` 6,2 s) ; - **≈ 6 s** viennent donc de la lecture à froid et **≈ 6 s** de l'analyse en Blueprint (`PopulateScenes` 3,6 s, `PopulateActions` 1,9 s…), à chaque passage. Conséquences pour la suite : - **Étapes 2 et 3, réunies** (un fichier compilé lu une fois, puis `LoadTxt` servi 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.