LifePlay-Revival/Docs/Migration/etat/ST/STG/STG-B2q-DIAG.md
edujiro5972 8084622450 LifePlay UE 5.8 : état de développement au 2026-10-19
Tickets : REP1-T4

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 22:57:42 +02:00

17 KiB
Raw Blame History

Fiche STG-B2q-DIAG — Niveau N3 — Modèle prévu claude-opus-5-5 | utilisé claude-opus-5-5 — Agent orchestrateur STG (session principale) — Skills lp-lot, sk-protocol

STG-B2q-DIAG : personnages assis éliminés par le rendu (2026-10-14)

Fiche B2q, confiée à STG par Big Boss (CAM est pris par B2p ; le sujet touche le maillage des Person). DIAG en lecture seule, sans UE et sans écriture hors de ce livrable. Lot STG, registre STG-TACHES.md.

Faits donnés par Big Boss :

  • COMMUN-6, 05:28-05:32, au bar : la PNJ d'en face, puis le joueur assis, disparaissent selon l'angle de C2. hidden=0, et aucune ligne T-occ : le rayon caméra → tête était libre.
  • COMMUN-7, 07:48, au café (« Having a meal ») : « Bridget a disparu ». Le joueur est assis fnt_new048, place _67 (journal : OccupyingFnt _67 dès 07:47:45, currentAnimation=fnt_new048-f-0-sit, meshZ=-80.4) ; la capture montre une chaise vide.

Point de départ : hypothèse de CAM (etat\CAM\CAM-COMMUN6-DIAG.md § 8), reprise et vérifiée ci-dessous.

1. Sources

Repère Fichier
E1 moteur UE 5.8, Engine\Source\Runtime\Engine\Private\Components\SkeletalMeshComponent.cpp l. 3417-3495 (USkeletalMeshComponent::CalcBounds)
E2 idem, SkinnedMeshComponent.cpp l. 2169-2175 (CalcBounds) et l. 2225-2300 (CalcMeshBound)
P etat\portage55\L6f\L6f_dump_Person.txt : graphes de Person (UserConstructionScript l. 1-12, NewProxy l. 1851-1955)
C etat\CAM\CAM-T4_LPDumpComponents_20261011-004910.txt : composants SCS de Person (PenisSM, HairSM, DirtyTalkSM, parents CharacterMesh0)
A Content\BPs\Person.uasset : table des noms (grep -c -a)
I Config\DefaultEngine.ini l. 30
J journal en cours de COMMUN-7 (café)

2. Ce qui est établi

2.1 Comment UE 5.8 calcule les bornes de rendu d'un SkeletalMesh (E1, E2)

USkeletalMeshComponent::CalcBounds appelle CalcMeshBound(RootBoneTranslation, bHasValidBodies, …). Dans CalcMeshBound, les cas sont examinés dans cet ordre :

  1. composant invisible, ou bComponentUseFixedSkelBounds : bornes de l'asset ;
  2. composant leader en bornes fixes : bornes de l'asset du leader ;
  3. leader avec bUseBoundsFromLeaderPoseComponent : bornes du leader ;
  4. asset physique avec corps : AABB des corps, qui suivent les os, donc la pose ;
  5. leader avec asset physique : idem, sur les corps du leader ;
  6. sinon, bornes importées de l'asset (pose de référence, debout), décalées de la seule translation de l'os racine ;

puis BoxExtent *= BoundsScale, autour du même centre.

Sans asset physique, les bornes ne suivent donc pas la pose : seul le déplacement de l'os racine les déplace.

2.2 Les maillages des Person

  • Pas d'asset physique sur bridget_gp ni michael (CAM § 8 : aucun import PhysicsAsset). Les corps tombent dans le cas 6.
  • Composants (C) :
    • le corps est CharacterMesh0, hérité de ACharacter ;
    • PenisSM et HairSM lui sont attachés. UserConstructionScript leur donne le corps comme leader pose (P l. 1-12) ;
    • DirtyTalkSM est un widget.
  • Vêtements, cheveux et accessoires ajoutés par Person::NewProxy (P l. 1851-1955) : sur chaque nouveau composant, SetBoundsScale(3.0), SetCastShadow(false), SetRenderCustomDepth(true), bUseAttachParentBound = true, puis SetLeaderPoseComponent(Mesh). Ces composants prennent donc les bornes du corps, et leur BoundsScale 3 est sans effet (les bornes du parent sont reprises telles quelles). Conséquence : quand le corps est éliminé, tout disparaît avec lui (vêtements, cheveux). C'est bien « la chaise vide ».
  • Corps (CharacterMesh0) : aucun graphe de Person ne règle ses bornes. La table des noms (A) ne contient ni bComponentUseFixedSkelBounds, ni bUseBoundsFromLeaderPoseComponent, ni bIncludeComponentLocationIntoBounds. Ses 3 occurrences de BoundsScale s'expliquent par SetBoundsScale / NewBoundsScale, ses 2 de bUseAttachParentBound par le nœud de NewProxy. Une valeur de BoundsScale stockée sur le gabarit du corps n'est pas exclue sans lecture MCP. Estimé : 1 (défaut).
  • r.AllowOcclusionQueries=True (I) : les requêtes d'occlusion sont actives.
  • Aucun C++ du projet ne touche aux bornes ni au culling (grep de BoundsScale, bUseAttachParentBound et LeaderPose dans Source/ : 0).

2.3 Les poses assises

  • Assis, le corps joue l'animation de meuble dans l'Anim BP (anim=bp:Daily_F_C currentAnimation=fnt_new048-f-0-sit), et le composant est relevé (meshZ -80,4 au lieu de -90). Les bornes restent celles de la pose debout, autour de la racine.
  • Ce DIAG n'établit pas de combien le corps s'écarte de la racine dans ces animations. Le journal ne relève ni les os en XY ni les bornes. Les relevés M1d (COMMUN-6) ne donnent que des hauteurs, en scène de couple.

3. Cause (estimée, forte)

Le corps assis est éliminé parce que ses bornes, celles de la pose debout autour de la racine, ne contiennent plus le corps. Les animations de meuble déplacent le bassin et non la racine. Deux mécanismes sont possibles, selon l'angle :

  • occlusion : les bornes sont derrière la table, le comptoir ou le dossier, alors que le corps dépasse et est visible. La requête d'occlusion les juge cachées et élimine le maillage entier, vêtements compris. C'est le plus probable au bar et au café (tables), en C2 qui tourne autour ;
  • frustum : les bornes sont hors du champ alors que le corps y est.

hidden=0 et l'absence de T-occ sont compatibles avec les deux. Trancher entre eux, et mesurer l'écart, demande le témoin du § 5.

À exclure, peu probable :

  • la distance d'affichage (MaxDrawDistance / CullDistance) : le joueur assis est proche ;
  • le LOD : un maillage n'est pas éliminé par le LOD ;
  • VisibilityBasedAnimTickOption : il arrête l'animation, pas l'affichage.

Observation annexe (hors B2q) : l'assiette et le sandwich qui flottent près de l'épaule de la PNJ au café sont un accessoire de place mal attaché. Mineur ; à noter pour plus tard.

4. Correctif proposé (C++ sans asset ; rien n'est écrit sans GO)

Id Geste Coût d'écriture Coût de rendu Risque
B2q-a (recommandé) BoundsScale adaptatif du corps. Toutes les 0,5 s, pour chaque Person_C visible de la pièce, on calcule l'écart entre le bassin (hip, sinon pelvis, sinon l'os 0) et le centre des bornes du corps, puis le facteur S = max(1, (écart + rayon des bornes) / rayon des bornes), borné à 4. On ne l'applique qu'en cas de changement de plus de 10 % : SetBoundsScale(S), UpdateBounds(), MarkRenderStateDirty(). Une ligne de journal par changement. Debout, S = 1 : pas de surcoût. Assis, couché ou en meuble, S couvre le corps déplacé. Les vêtements suivent (bUseAttachParentBound). ≈ 50 lignes C++ (DirectControl ou Debug, fichier STG), N3, VAL, 1 build seulement pour les personnages assis : leurs bornes sont jusqu'à 4 fois plus grandes, donc ils sont un peu plus souvent dessinés hors champ ou cachés (ombres comprises). Faible pour une dizaine de corps ; à mesurer au bar (stat unit avant/après) faible : les bornes de rendu ne servent ni aux collisions ni aux tracés
B2q-b (repli, plus simple) BoundsScale = 3 fixe sur le corps de toutes les Person (balayage toutes les 2 s, comme le propose CAM) ≈ 30 lignes constant, sur tous les personnages, même debout faible ; il peut ne pas suffire si l'écart dépasse ≈ 1,2 m
B2q-c Asset physique pour bridget_gp et michael : des bornes exactes qui suivent les os 2 gros assets dans l'éditeur, hors alpha nul les corps entrent dans les tracés Visibility (sondes C2, T-occ)
B2q-d r.AllowOcclusionQueries=False 1 ligne de config global (tout le jeu) ne règle pas le cas frustum ; non recommandé

bIncludeComponentLocationIntoBounds (suggéré par Big Boss) n'ajoute à la boîte que le point d'origine du composant (E2 l. 2173-2175, E1 l. 3472-3487). Cela ne couvre pas un corps déplacé : non retenu.

5. Témoin proposé (T-cull, à mettre dans le même build ; recommandé même avec B2q-a)

Dans LPDebugSubsystem (relevé des personnes, actif avec -LPPersonsLog), toutes les 0,5 s, pour chaque Person_C non cachée à moins de 15 m de la caméra :

  • une ligne de mesure par changement de pose de meuble (currentAnimation ou OccupyingFnt) : T-cull mesure <Person> anim=<fnt…> bassin a %.0f cm du centre des bornes (dans=%d) ; bornes %.0f x %.0f x %.0f ; BoundsScale %.2f ; physAsset=%d ;
  • une ligne d'alerte si le bassin est à l'écran (ProjectWorldLocationToScreen dans le viewport) et que le corps n'a pas été rendu depuis 0,2 s (WasRecentlyRendered(0.2f) faux) : T-cull : <Person> non rendue, bassin a l'ecran, a %.0f cm du centre des bornes (dans=%d), occlusion=%d.

Ces lignes chiffrent l'écart réel des poses assises et tranchent entre occlusion et frustum (dans=0 avec le centre des bornes hors du champ : frustum). Elles diront aussi si B2q-a suffit. Coût : ≈ 35 lignes, 1 build ; journal seulement.

5b. Complément (Big Boss, café, 07:48-07:49)

L'utilisateur rapporte : « les deux ont disparu ». Les deux personnages assis à la même table (le joueur et la PNJ) disparaissent en même temps, sous un même angle de C2. Cela va dans le sens du § 3 : deux corps assis à la même table ont chacun leurs bornes debout centrées sur leur racine, et les deux boîtes passent ensemble derrière le même plateau ou hors du champ au même angle. Une cause propre à un personnage (vêtement, animation, hidden) est moins probable. Le mécanisme occlusion par la table reste le plus probable ; le témoin T-cull le tranchera (dans=0 et occlusion=1 attendus pour les deux à la même heure).

6. Estimation et ordre proposé

  1. T-cull et B2q-a dans le même build (COMMUN-8 ou suivant), avec une VAL statique : ≈ 85 lignes, N3, 1 build.
  2. Essai :
    • le bar (C2 autour de la PNJ d'en face, puis du joueur assis) ;
    • le café, assis à fnt_new048 ;
    • un personnage couché ;
    • stat unit avant et après, au bar.
  3. Si une disparition persiste avec une ligne T-cull à dans=1, la cause n'est pas les bornes : ouvrir une fiche Ombres/occlusion.

7. Fichiers à commiter

Docs/Migration/etat/ST/STG/STG-B2q-DIAG.md.

Tours : 14

8. Complément après l'essai COMMUN-8 : B2q-a insuffisant au café (2026-10-14)

Demande de Big Boss : l'utilisateur dit « manque l'homme » (café, vers 09:09) ; l'homme assis est invisible, son téléphone flotte. DIAG en lecture seule, sans UE.

8.1 Ce que dit le journal (établi)

Source : D:\Game\LifePlay_Build_5.8_COMMUN-8_Development\Windows\LifePlay\Saved\Logs\LifePlay.log (10 128 lignes à la lecture).

  • Bar, chambre (B2q-a a suffi) : bassin à 13-123 cm du centre des bornes selon le meuble (fnt_chair06 : 123 cm, une autre place : 47 cm) ; S monte à 1,5-4 et l'écart est couvert.
  • Café (cafe___vin01, chargé à 09:07:11, places fnt_new048 _59, _60, _66, _67) : bassin à 290 cm (hommes, anim. fnt_new048-m-0-sit) et 297 cm (femmes, -f-0-sit) du centre des bornes. Les mesures sont identiques pour les quatre personnes de même sexe, au cm près. S plafonne à 4, et les alertes T-cull : … non rendue … dans=0, centre a l'ecran=0 sont fréquentes : PlayerCharacter 86, Person_C_2147481930 34, …906 2, …954 1.
  • Les capsules (LPDebug persons) sont sur les places : PlayerCharacter en (-3131768, -14967061) sur _59, …930 sur _60, la chaise sous chacun (visibleComp = la place, -41,1). Le téléphone flotte « à sa place » sur la capture. Le corps est donc à la place, et c'est le centre des bornes qui est à ≈ 3 m.
  • Fait nouveau, qui corrige le § 2.2 du DIAG : à la première vue de chaque personne, la ligne B2q-a part de BoundsScale 3.00 (5 lignes 3.00 -> …, dont 3 3.00 -> 1.00). Le corps a déjà BoundsScale 3 dans le jeu d'origine : c'est le réglage du gabarit ou d'un Blueprint (le même 3 que NewProxy). L'estimation « 1 (défaut) » du § 2.2 était fausse. B2q-a ramène les personnes debout à 1 : c'est une baisse par rapport à l'origine (risque R3 de la VAL réalisé). Elle est sans dommage visible debout, puisque le bassin est à 13-16 cm du centre, mais il faut la corriger.

8.2 Pourquoi le centre des bornes est à 3 m (estimé, fort)

Sans asset physique, les bornes sont celles de l'asset, décalées de RootBoneTranslation, la translation de l'os racine dans la pose courante (§ 2.1 ; moteur SkeletalMeshComponent.cpp l. 3449-3470). La capsule et le corps sont sur la place, et les bornes sont à 290 ou 297 cm, avec une valeur fixe par animation (hommes 290, femmes 297, sur 4 places différentes). Lecture : l'animation de meuble fnt_new048-*-0-sit déplace l'os racine d'≈ 3 m, et l'os du bassin compense en sens inverse. Le corps reste sur la place, mais UE croit que le maillage a suivi la racine. C'est la même cause que pour les écarts plus petits (fnt_chair06 : 123 cm). L'amplitude dépend de l'animation, sans doute de la façon dont elle a été créée ou convertie : racine au pivot du groupe de meubles. Non établi : la position de l'os racine n'est pas au journal. Le témoin du § 8.4 l'écrira.

Plafond nécessaire avec B2q-a : le facteur s'applique de façon uniforme aux trois axes. Un écart de 290 cm le long de l'axe mince des bornes (demi-étendue 13 cm, épaisseur du corps en pose de référence) demande S ≈ (290 + 13) / 13 ≈ 23, soit des bornes de ≈ 6 × 29 × 41 m. À ce niveau, la personne n'est plus jamais éliminée : la culling est de fait coupée pour elle.

8.3 Correctif proposé B2q-b (rien n'est écrit sans GO)

Id Geste Coût d'écriture Coût de rendu Risque
B2q-b1 (recommandé pour l'alpha) Dans FitPersonBounds : (1) plancher = l'échelle d'origine de chaque personne, relevée à la première vue (3 dans le jeu d'origine) : plus jamais en dessous, ce qui corrige la baisse de B2q-a ; (2) plafond porté à 25 ; le facteur est calculé comme aujourd'hui, au besoin réel par axe. ≈ 15 lignes, N3, VAL, 1 build seulement pour les personnes dont la pose sort des bornes (au café, toutes les assises) : elles ne sont plus jamais éliminées (frustum ni occlusion), ombres comprises. Au café, 4 à 6 corps Daz (≈ 50-100 k triangles chacun) toujours dessinés. Estimé faible à modéré ; à mesurer par les lignes LPDebug hitch au café (COMMUN-8 contre le build suivant) faible : aucun effet sur collisions ni tracés ; journal inchangé (une ligne par changement de plus de 10 %)
B2q-b2 (après l'alpha, juste) Recentrer les bornes sur le bassin : réécrire RootBoneTranslation du corps avec la position du bassin (en espace composant) après l'évaluation de l'animation et avant le calcul des bornes ; les bornes suivent alors le corps à S = 3 ≈ 30 lignes, mais l'ordre des ticks (animation, puis bornes, puis notre ticker) n'est pas établi sans essai ; N4 nul moyen : RootBoneTranslation est recalculé à chaque évaluation ; l'écriture peut être écrasée ou arriver trop tard (une image de retard)
B2q-b3 (après l'alpha) Asset physique minimal créé en mémoire (un corps sphérique sur l'os du bassin, PhysicsAssetOverride), collision du corps mise à NoCollision : les bornes suivent les os (cas 4 du § 2.1) ≈ 40 lignes, N4 nul élevé sans essai : création des corps physiques, entrée dans les tracés Visibility si la collision n'est pas coupée à temps, chemin bHasValidBodies à vérifier
B2q-b4 Corriger les animations de meuble (racine au siège) assets, hors alpha nul conversion de toutes les fnt_*

Recommandation : B2q-b1 pour l'alpha (simple, sûr, coût borné aux seules personnes assises loin de leur racine), plus le témoin du § 8.4. B2q-b2 sera étudié après l'alpha si le coût mesuré gêne.

8.4 Témoin complété (même build, ≈ 5 lignes)

La ligne T-cull mesure donnera aussi la distance de l'os racine (os 0) au bassin et au composant : … racine a %.0f cm du bassin, a %.0f cm du composant. Une racine à ≈ 3 m du bassin et du composant établit le § 8.2.

8.5 Cas d'essai à ajouter (build suivant)

  • Café : assis au comptoir ou à une table fnt_new048, avec les PNJ assis ; tourner C2 tout autour. Plus aucune disparition, plus aucune alerte T-cull … non rendue ; B2q-a : … BoundsScale 3.00 -> 2x.xx et racine a ≈ 290-300 cm du bassin.
  • Debout : aucune ligne B2q-a … -> 1.00 (plancher à l'échelle d'origine).
  • Coût : lignes LPDebug hitch au café, comparées à COMMUN-8.