31 KiB
Fiche STA-T2b-VILLE — Niveau N3 — Modèle prévu (modèle de l'agent lp-cart) | utilisé claude-opus-5-5 — Agent lp-cart — Skills sk-protocol, ue-cpp-build, lp-commandlets, lp-paths
STA-T2b-VILLE-DIAG : StreetMap_Static, Room.pickPresetWorld, familles (Script Msg) et hitchs MapMarkers (2026-10-09)
Hors gabarit : partiel, annoncé par la fiche. Une sous-section DIAG 1-5 par clé (K1 à K9), puis § Constats (tableau récapitulatif, clés non traitées, compte rendu sk-protocol § 3).
Lecture seule : ni jeu, ni éditeur, ni commandlet, ni build. Seul fichier écrit : ce livrable.
Abréviations : CIBLE = D:\Game\LifePlay_Build_5.8_Development_U8_essai\Windows\LifePlay\Saved\Logs\LifePlay.log ; REF = D:\Game\LifePlay-master 5.5\Docs\Migration\etat\U58\U6\LifePlay_58_session2.log ; dumps\ = D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ST\STA\dumps\ ; Src\ = D:\Game\LifePlay-master 5.8\Source\LifePlay\ ; E58\ = D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\.
Deux mécanismes moteur servent à toutes les clés (lus dans le moteur 5.8 installé) :
- Forme
Script Msg: Attempted to access index …(sans ligneFunction, sans pile) : émise parUKismetArrayLibrary::GenericArray_Get(nœud Get par copie) viaFFrame::KismetExecutionMessage; la valeur rendue est remise à la valeur par défaut (None, 0) et la fonction continue (E58\Engine\Private\KismetArrayLibrary.cpp:459-480). Cela confirme le point amont de STA-T1 § Écarts (pas de ligneFunctionpour ces événements). - Forme
Accessed None trying to read (real) property P in <classe>: P est la propriété objet qui vaut None et sert de contexte (E58\CoreUObject\Private\UObject\ScriptCore.cpp:3203-3218). Forme nueAccessed None:Stack.MostRecentPropertyest nul (ScriptCore.cpp:3220-3228). Forme « pending kill or garbage » : objet détruit mais pas encore collecté (ScriptCore.cpp:3194-3201).
K1. StreetMap_Static_C:SearchByAmenitySafe : CurrentCityExpansion in GI_C (9 / 14) et forme nue (1 / 1)
1. Symptôme et reproduction
- CIBLE:7898-7910 :
Accessed None trying to read (real) property CurrentCityExpansion in /Game/BPs/GI.GI_C,Function …StreetMap_Static_C:SearchByAmenitySafe:64X; pile :CentralLondon_C:ReceiveTick→GI_C:UpdateTime→TopRight_C:GenerateRecs→Person_C:recommendActions→recommendKeyActions→recommendHomeIfNeeded→SearchByAmenitySafe. - CIBLE:51374-51386 : même message ; pile :
Scene_Cbouton Next →GI_C:ContinueScene→ReadSceneLine→CallFunction→MakePermanent→Person_C:assignWork→SearchByAmenitySafe. - Forme nue : CIBLE:51388-51400, même fonction, même milliseconde (16.45.55:195) et même pile que 51374.
- Comptes (Grep
count, motifWarning: Accessed None trying to read \(real\) property CurrentCityExpansion) : CIBLE 9, REF 16 (= 14SearchByAmenitySafe+ 2findNearbyBuilding,STA-T1-INV.md:135,151).
2. Hypothèse testée
GI.CurrentCityExpansion vaut None parce qu'aucun emplacement de sauvegarde d'extension de ville n'existe, et SearchByAmenitySafe lit CurrentCityExpansion.Buildings sans test IsValid.
3. Essai et résultat brut
- Nœud fautif :
dumps\StreetMap_Static__SearchByAmenitySafe.txt:11-19(VariableGet 'GI'→VariableGet 'CurrentCityExpansion'→VariableGet 'Buildings') ;BuildingsalimenteVariableSet_3(Shuf, l.175-179, branche « Amenity non vide »),CallArrayFunction_3(Array_Length, l.155-158) etFunctionResult_3(l.169-171) (branche « Amenity vide »,IfThenElse_6l.164-168). Les 47 nœuds ne contiennent aucunIsValid: les deux seulsMacroInstancesont les boucles (l.23-30, l.87-94). - Écriture de la variable,
dumps\GI__EventGraph.txt: événement à paramètreCityName(CustomEvent_1141, l.11365-11368) →DoesSaveGameExist(CityName)(l.11369-11375) →IfThenElse_2072(l.11376-11380) :else(etCastFailed, l.11397) →VariableSet_4287 'CurrentCityExpansion'avec entrée vide, donc None (l.11388-11393) ;then→LoadGameFromSlot→ cast →VariableSet_4288(l.11381-11387, 11401-11406). Appelé parLoadCityExpansion(CityName)aprèsSortStreetMapData(l.11411-11415, 13174-13177). L'objet n'est créé qu'à l'ajout d'un bâtiment (CustomEvent_447,IsValid→Is Not Valid→CreateSaveGameObject→VariableSet_5455, l.11323-11328, 11416-11426, 11437-11442) puis écrit parSaveGameToSlot(l.11443-11450). - Glob
*.savdansD:\Game\LifePlay_Build_5.8_Development_U8_essai\Windows\LifePlay\Saved\SaveGames: 2 fichiers,GameSettings.sav,Default.sav; aucun emplacement de ville. - Effet en jeu, lu dans le dump : branche « Amenity vide » :
Array_Length(None)= 0 →FunctionResult_0rendStreetMap.Buildings(l.159-174) ; branche « Amenity non vide » :Shufvide → boucle vide →Temp(variable locale, l.60-63) vide →IfThenElse_2.then→ boucle surStreetMap.Buildings(l.82-86, 187-198). Le repli voulu a lieu.
4. Verdict : confirmée
Établi : la variable vaut None tant que la ville n'a pas d'extension sauvegardée, état normal d'une ville jamais modifiée. Le résultat de la fonction est juste (repli sur StreetMap.Buildings) ; l'avertissement est du bruit. Forme nue : même appel ; le nœud exact n'est pas départagé entre les lectures de VariableSet_3 et CallArrayFunction_3 (incertain) ; le garde ci-dessous couvre les deux.
Correctif proposé (Blueprint StreetMap_Static, fonction SearchByAmenitySafe), garde justifié :
- (a) entre
IfThenElse_5.thenetVariableSet_3: macroIsValidsurGI.CurrentCityExpansion;Is Valid→VariableSet_3;Is Not Valid→VariableSet_4(boucleStreetMap.Buildings,Tempest encore vide). - (b) entre
IfThenElse_5.elseetIfThenElse_6: mêmeIsValid;Is Valid→IfThenElse_6;Is Not Valid→FunctionResult_0. - Même garde dans
findNearbyBuilding(REF 2, non dumpée). - Non recommandé : créer un objet vide dans
LoadCityExpansionau lieu de None ;SaveGameToSlot(l.11443-11450) écrirait alors un emplacement de ville sans changement voulu.
5. Hypothèse suivante
Aucune. Suite : correction Blueprint (N2 lp-impl), puis VAL N1 : rejouer le parcours CIBLE ; attendu : 0 ligne property CurrentCityExpansion, 0 forme nue sous SearchByAmenitySafe.
K2. StreetMap_Static_C:ExecuteUbergraph_StreetMap_Static : BGA in StreetMap_Static_C (5 / 6, + 4 « pending kill » en REF)
1. Symptôme et reproduction
- CIBLE:7446-7462 :
Accessed None … property BGA; pile :Action_Cbouton →GI_C:InterruptAnyCurrentAction→StopDurationUpdate→MatchCurrentPlayerBuilding→Room_C:ShowCurrentPlayerBuilding→StreetMap_Static_C:PlayBGA. - CIBLE:7741-7756 : pile
GI_C:TakeActionWithBuilding→StreetMap_Static_C:PlayerGoHere→UpdateWall→PlayBGA→ExecuteUbergraph_StreetMap_Static. - CIBLE:7974-7978 : pile réduite à
ExecuteUbergraph_StreetMap_Static. - REF:8942-8953 :
Attempted to access AudioComponent_2147460819 via property BGA, but … is not valid (pending kill or garbage). - Comptes (Grep
count) : CIBLE 5 ; REF 10 (motifproperty BGA|via property BGA= 6 Accessed None + 4 pending kill,STA-T1-INV.md:137,191).
2. Hypothèse testée
BGA (composant audio) vaut None avant le premier SpawnSound2D (et redevient None après la collecte du composant auto-détruit) ; l'événement PlayBGA lit BGA.Sound et appelle BGA.Stop() sans IsValid.
3. Essai et résultat brut (dumps\StreetMap_Static__EventGraph.txt)
- Événement à paramètre
Amenity(CustomEvent_13, l.5417-5420 ; nomPlayBGAestimé : appel?::PlayBGA()à paramètreAmenity, l.5453-5457, et pile CIBLE:7755-7756) →PlayStreetBGA = false(l.5486-5491) →IfThenElse_22surMap_Find(AmenityBGAs, Amenity)(l.5492-5505). else→CallFunction_134BGA.Stop()(l.5443-5446) : lecture 1.then→IfThenElse_23surEqualEqual_ObjectObject(Value, BGA.Sound)(VariableGet_130, self = BGA, l.5458-5460, 5506-5515) : lecture 2 ;else→SwitchString_3:street→PlayStreetBGA = true→RetriggerableDelay 0.5→IfThenElse_21→CallFunction_124(l.5465-5485) ;Default→CallFunction_124BGA.Stop()(l.5461-5464) : lecture 3 →SpawnSound2D(bAutoDestroy = true)→VariableSet_32 'BGA'(l.5421-5439).- Grep
'BGA'sur le dump : 2 nœuds seulement (VariableSet_32l.5434,VariableGet_129l.5440) : un seul écrivain, aucunIsValid. - CIBLE:7977-7978 (une seule trame
ExecuteUbergraph) : reprise latente duRetriggerableDelayde la branchestreet(estimé). - REF « pending kill » :
bAutoDestroy = 'true'(l.5432) ; composant détruit à la fin du son, encore référencé avant le GC (estimé) ; après le GC la référence vaut None (estimé).
4. Verdict : confirmée
Établi : 3 lectures de BGA sans garde. Bénin : Stop sur None ne fait rien et la comparaison rend faux, donc le son est lancé quand même.
Correctif proposé (Blueprint StreetMap_Static, graphe d'événements), garde justifié (None est l'état initial) :
- (a)
IfThenElse_22.then→IsValid(BGA);Is Valid→IfThenElse_23;Is Not Valid→SwitchString_3.execute. - (b)
IfThenElse_22.else→IsValid(BGA);Is Valid→CallFunction_134;Is Not Valid→ fin. - (c) devant
CallFunction_124(deux entrées :SwitchString_3.Default,IfThenElse_21.then) →IsValid(BGA);Is Valid→CallFunction_124;Is Not Valid→CallFunction_110(SpawnSound2D).IsValidécarte aussi les objets « pending kill or garbage », donc les 4 lignes REF.
5. Hypothèse suivante
Aucune. VAL N1 : parcours ville (clic bâtiment, PlayerGoHere, rue) ; attendu : 0 ligne property BGA ou via property BGA.
K3. Room_C:pickPresetWorld : index hors bornes BuildingPoints (4 / 10)
1. Symptôme et reproduction
- CIBLE:7465-7483 :
Attempted to access index 1 from array BuildingPoints of length 0!; pileAction_C→GI_C:InterruptAnyCurrentAction→ … →Room_C:ShowCurrentPlayerBuilding→ShowCurrentWorldPreset→pickPresetWorld; CIBLE:7485-7503 : index 0, même milliseconde. - CIBLE:7759-7791 : même paire ; pile
TakeActionWithBuilding→PlayerGoHere→UpdateWall→Room_C:ShowCurrentWorldPreset→pickPresetWorld. - CIBLE:7505 et 7795, juste après chaque paire :
[Room_C_0] Modules/vin_Base/World/street___vin01.lpworld test0203. - Comptes (Grep
count,Warning: Attempted to access index \d+ from array BuildingPoints) : CIBLE 4, REF 10.
2. Hypothèse testée
Le bâtiment passé n'a pas de polygone (joueur dans la rue), et pickPresetWorld lit BuildingPoints[0] et [1] sans test de longueur quand BackgroundsSaved ne connaît pas le bâtiment.
3. Essai et résultat brut (dumps\Room__pickPresetWorld.txt)
- Entrée
(Building, Amenity)→GI.BuildingPointsToString(BuildingPoints)→Map_Find(GI.BackgroundsSaved)→IfThenElse_0: trouvé →FunctionResult_1; sinonVariableSet_1 len = Array_Length(WorldPresets[Amenity].Strings)(l.2-13, 106-112, 136-158). GetArrayItem_0(index 0) etGetArrayItem_1(index 1) surBuildingPoints(l.20-23, 36-39) → graineRound(P0.X + P0.Y + P1.X + P1.Y)(l.29-35, 51-58) →FMod(graine, len)→Abs→Round→Strings[i](l.45-50, 63-66, 83-86, 113-116) →Select(Strings[i], Strings[0], Len > 0)(l.117-135) →PrintString(… + ' test0203')(l.67-82). Aucun test de longueur surBuildingPoints.BuildingPointsest un membre natif deFStreetMapBuilding(D:\Game\LifePlay-master 5.8\Plugins\StreetMap\Source\StreetMapRuntime\Public\StreetMap.h:300-302).- Grep
\[Room_C_0\] .* test0203sur CIBLE : 7 lignes (7505, 7795, 7994, 8033, 37861, 49553, 51570) ; seules les deux premières (rue) suivent des avertissements ; la 3e lignestreet(8033) n'en a pas, donc le bâtiment passé y avait des points.
4. Verdict : confirmée
Établi : BuildingPoints de longueur 0 avec un préréglage street ; tableau vide normal (rue, aucun bâtiment). Effet : la graine vaut 0 et le préréglage retenu est Strings[0] (street___vin01), choix fixe sans défaut visible (estimé).
Correctif proposé (Blueprint Room, fonction pickPresetWorld), garde justifié : Branch sur Array_Length(BuildingPoints) >= 2 entre IfThenElse_0.else et VariableSet_1 ; vrai → chemin actuel ; faux → VariableSet_2 string = GetArrayItem_3 (Strings[0]) → PrintString → FunctionResult_0. Risque voisin, non observé : len = 0 (aucun préréglage pour l'amenity) donne FMod par 0 (l.45-48) ; le même Branch peut tester len > 0.
5. Hypothèse suivante
Aucune. VAL N1 : rue au chargement ; attendu : 0 ligne array BuildingPoints, préréglage street___vin01 inchangé.
K4. GI_C:(Script Msg) : Person_24 in Variable (39 / 59)
1. Symptôme et reproduction
- CIBLE:38010-38022 :
Script Msg: Attempted to access index 0 from array 'Person_24_4B71…' of length 0 in '/Game/Structs/Variable.Variable'!,called by: GI_C, suivi à la même milliseconde deAccessed None trying to read (real) property CallFunc_Array_Get_Item in not an UClass,Function …GI_C:clearVariable:64X; pileGI_C:UpdateCheckForScenes→CheckConditionsWho→ReadSceneLine→CallFunction→getPerson. - CIBLE:38063-38075 : idem ; pile se terminant par
GI_C:getRelative. - Comptes (Grep
count,Script Msg: Attempted to access index \d+ from array 'Person_24_) : CIBLE 39 ; REF 59 (STA-T1-INV.md:121, cohérent avec le compte REF regroupé du § Constats).
2. Hypothèse testée
clearVariable lit GetVariable(Var).Person[0] sans test de longueur, pour une variable de scène qui ne contient aucune personne.
3. Essai et résultat brut (dumps\GI__clearVariable.txt)
GetVariable(Var)→BreakStruct Variable→Person_24_…→GetArrayItem_0, index 0 (l.5-24). La sortie sert àEqualEqual(Companion),EqualEqual(Interacting),Prefix,SaveSlot,Name_First,OccupyingMoreVar,DestroyPerson(l.24, 39-151). Seul test :Len(Var) > 0(l.25-38) ; aucun test sur la longueur du tableau.- Grep avec contexte (
CallFunc_Array_Get_Item in not an UClass,-B 1 -A 2) : chaqueScript Msg Person_24est suivi d'un ou deuxAccessed NonedeclearVariableà la même milliseconde (CIBLE:48954-48968 : deux ; CIBLE:38010-38012 : au moins un).
4. Verdict : confirmée
Établi : même événement que la famille GI_C:clearVariable (72 / 94, STA-T1-INV.md:117, fiche STA-T2b-GIVAR). Variable vide = état possible d'une condition de scène (estimé). Remarque : si Companion vaut None, None == None rend vrai et la fonction ne fait rien (l.46-63, IfThenElse_1.then vide).
Correctif proposé (Blueprint GI, fonction clearVariable), garde justifié : Branch sur Array_Length(Person_24) > 0 entre CallFunction_0.then (GetVariable) et IfThenElse_1 ; faux → retour. Supprime le Script Msg et les Accessed None qui le suivent (la part exacte des 72 reste à compter par GIVAR). À fusionner avec la proposition de STA-T2b-GIVAR (même nœud).
5. Hypothèse suivante
Aucune pour la clé. Consolidation STA-T2c : une seule correction GIVAR + VILLE.
K5. GI_C:(Script Msg) : Texture2dArray_3 in Te2dArray (6 / 0)
1. Symptôme et reproduction
- CIBLE:51230-51231 :
Script Msg: Attempted to access index 0 from array 'Texture2dArray_3_E303…' of length 0 in '/Game/Structs/Te2dArray.Te2dArray'!,called by: GI_C(trame 954, début de la scène de couple, juste avantShow couple : brancheCIBLE:51232). - CIBLE:51255-51256 : trame 752, juste après
[SexAction_C_…] MF_sp01 (Animation String)(CIBLE:51254). Autres : CIBLE:51290, 51307, 51322, 51346 (Grep : 6 lignes). - Pas de pile (forme
Script Msg).
2. Hypothèse testée
Une fonction de GI lit Te2dArray.Texture2dArray[0] sur un tableau vide au changement d'animation de la scène de couple.
3. Essai et résultat brut
- Grep
Texture2dArray:dumps\GI__EventGraph.txt0 ;dumps\GI__graphes.txt0 (noms de graphes seulement) ;dumps\Person__EventGraph.txt0. - « called by: GI_C » (instance) : fonction propre à
GIhors graphe d'événements, non dumpée (estimé). - Grep
Te2dArraysurContent\**\*.uasset: 0, non concluant (ripgrep saute les fichiers binaires).
4. Verdict : indécise (nœud non localisé)
Nouvelle en CIBLE parce que REF ne joue pas la scène de couple (STA-T1-INV.md:258). Correctif générique, à confirmer sur le nœud : Array_IsValidIndex(Texture2dArray, 0) avant le Get ; sinon texture par défaut ou rien.
5. Hypothèse suivante (N0 puis N3)
N0 lp-builder : LPDumpFunction -BP=GI -Fn=<f> -Pins -Exec sur les candidats proches dans le temps (PlayAppropriateSexAnimation, PlayAnimationMorph, PersonPlayAnimationMorph, getFaceTexture, getMID, CumSound : dumps\GI__graphes.txt:80,8,81,267,26,269), puis Grep Texture2dArray_3. N3 ensuite pour le correctif.
K6. SexInterface_C:(Script Msg) : SexPersons in GI_C (3 / 0)
1. Symptôme et reproduction
CIBLE:51235-51240 : Script Msg: Attempted to access index 2, puis 3, puis 4, from array 'SexPersons' of length 2 in '/Game/BPs/GI.GI_C'!, même milliseconde (16.44.17:984), called by: SexInterface_C …GI_C_2147482540.SexInterface_C_2147464127. Pas de pile.
2. Hypothèse testée
SexInterface lit GI.SexPersons aux indices fixes 0 à 4 (cinq emplacements) sans test de longueur ; avec 2 participants, 3 lectures hors bornes.
3. Essai et résultat brut
SexInterfacen'a pas été dumpé ; l'asset existe (Glob :D:\Game\LifePlay-master 5.8\Content\UI\SexInterface.uasset).- Indices 2, 3, 4 consécutifs dans la même milliseconde : lectures à index fixe (estimé). Le Get rend None (
KismetArrayLibrary.cpp:479).
4. Verdict : indécise (nœud non localisé), mécanisme estimé
Bénin pour une scène à deux. Correctif générique : Array_IsValidIndex(GI.SexPersons, i) devant chaque emplacement, ou boucle ForEach sur SexPersons.
5. Hypothèse suivante (N0 puis N3)
N0 : LPDumpFunction -BP=SexInterface (liste des graphes), puis dump de la fonction qui lit SexPersons. N3 ensuite.
K7. Person_C:(Script Msg) : Standspots_Occupied in Room_C (15 / 9)
1. Symptôme et reproduction
- CIBLE:7635-7636 :
Script Msg: Attempted to access index 0 from array 'Standspots_Occupied' of length 0 in '/Game/BPs/Room.Room_C'!,called by: Person_C …PlayerCharacter, juste après une pile terminée parPerson_C:standIdle(CIBLE:7633). - CIBLE:19503 (index 0, longueur 0), 19573 (index 1, longueur 1), 19625 (index 2, longueur 2) : index = longueur à chaque fois.
- Comptes (Grep
count) : CIBLE 15 ; REF 9 (STA-T1-INV.md:134).
2. Hypothèse testée
standIdle parcourt Room.Standspots et lit le tableau parallèle Standspots_Occupied[i] ; celui-ci est rempli au fil de l'eau (Array_Set avec bSizeToFit), donc plus court que Standspots.
3. Essai et résultat brut (dumps\Person__standIdle.txt)
ForEachsurGI.Room.Standspots(MacroInstance_1, l.171-181) →GetArrayItem_0Standspots_Occupied[Array Index](l.182-188) →IsValid(MacroInstance_3, l.189-193) →Valid(l.197-204) ;Is Not Validou nonValid→Knot_1→Dest= emplacement libre (l.194-196, 205-209).- Écriture dans la même fonction :
Array_Set(Standspots_Occupied, Find(Standspots, Dest), self, bSizeToFit = 'true')(l.144-162).
4. Verdict : confirmée
Établi : tableau parallèle volontairement creux ; le Get rend None et l'emplacement est vu comme libre, ce qui est le comportement voulu. Bénin.
Correctif proposé (Blueprint Person, fonction standIdle), garde justifié : Branch sur Array_IsValidIndex(Standspots_Occupied, Array Index) avant MacroInstance_3 ; faux → Knot_1 (libre). Autre voie : dimensionner Standspots_Occupied à Array_Length(Standspots) là où Room remplit Standspots (Room non dumpé au-delà de pickPresetWorld).
5. Hypothèse suivante
Aucune. Les Accessed None qui suivent (OccupyingFnt, Near) relèvent de STA-T2b-PERSON.
K8. GI_C:(Script Msg) : WidgetComponents in MapMarkers_C (1 / 2)
1. Symptôme et reproduction
- CIBLE:7380-7399 :
Script Msg: Attempted to access index 0 from array 'WidgetComponents' of length 0 in '/Game/BPs/MapMarkers.MapMarkers_C'!(called by: GI_C), puisAccessed None … CallFunc_Array_Get_Item_53 in not an UClass(ExecuteUbergraph_GI) ; pileMainMenu_CContinue →GI_C:DelayedStart→PC_C:BeginAutoLoad→GI_C:AutoLoad→MoveCity→SpawnMapMarkers→FocusOnMapMarkers. - CIBLE:7413, 75 ms plus tard :
LogLifePlay: Display: MapMarkers : slot de focus WidgetComponents[0] ajoute (ERR-008, …). - REF:7451 et REF:8172 (Grep : 2).
2. Hypothèse testée
FocusOnMapMarkers lit MapMarkers.WidgetComponents[0] juste après l'apparition des marqueurs, avant que la garde C++ (tick de 0,25 s) n'insère son emplacement de focus.
3. Essai et résultat brut
dumps\GI__EventGraph.txt:13185-13212: événement sans paramètre (CustomEvent_183) →SetInputMode_GameAndUIEx(PC, MapMarkers.WidgetComponents[0].GetUserWidgetObject()); seule lecture deWidgetComponentsdans le graphe d'événements deGI(Grep : 1VariableGet, l.13191). NomFocusOnMapMarkersestimé (appel l.13213-13216 et pile CIBLE:7398-7399).- Garde :
Src\LPMapMarkersGuardSubsystem.cpp:61(tick 0,25 s), remplit le tableau seulement s'il est vide (l.89-125) ; en-têteSrc\LPMapMarkersGuardSubsystem.h:1-4(« GI.FocusOnMapMarkers lit MapMarkers.WidgetComponents[0] sans test de longueur », « Aucun Blueprint n'est modifié »). - Un événement par instance de
MapMarkers_C: CIBLE 1 instance (2147481658), REF 2 instances (2147481693, 2147479394, d'après les lignes de hitch).
4. Verdict : confirmée
Reste d'ERR-008 : une lecture par apparition de MapMarkers, sans plantage (SetInputMode avec widget None).
Correctif proposé (Blueprint GI, CustomEvent_183), garde justifié : Branch sur Array_IsValidIndex(MapMarkers.WidgetComponents, 0) après l'événement ; faux → SetInputMode_GameAndUIEx sans widget (comportement actuel), ou rien. Alternative C++ (garde lancée à l'apparition de l'acteur) non recommandée : un emplacement en tête avant les marqueurs risque de décaler les index par rapport à Vector2Ds (estimé, LPMapMarkersGuardSubsystem.h:3-4).
5. Hypothèse suivante
Aucune. Lien avec K9 : si ce correctif Blueprint est fait, la création du composant de focus par la garde (cause de K9) peut devenir inutile ; à décider (§ Constats, Q1).
K9. Hitchs MapMarkers_C.LPFocusWidgetComponent (2 / 4)
1. Symptôme et reproduction
- CIBLE:7972 (1,77 ms, trame 330, action « aller à ») et CIBLE:51241 (11,66 ms, trame 955, début de la scène de couple) :
LogUObjectGlobals: Warning: Gamethread hitch waiting for resource cleanup on a UObject (WidgetComponent …MapMarkers_C_2147481658.LPFocusWidgetComponent) overwrite took …ms. - REF:7736 (3,45 ms), 8321 (6,07), 9687 (3,14), 14480 (3,43).
- Comptes (Grep
count,LPFocusWidgetComponent\) overwrite took) : CIBLE 2.
2. Hypothèse testée
La garde recrée son composant de focus avec un nom fixe alors que le précédent (détruit par le Blueprint, pas encore collecté) existe encore dans le même acteur : NewObject reconstruit par-dessus et attend la fin du nettoyage côté rendu.
3. Essai et résultat brut
Src\LPMapMarkersGuardSubsystem.cpp:127:NewObject<UWidgetComponent>(Markers, TEXT("LPFocusWidgetComponent")), nom fixe. Ligne atteinte seulement si, après retrait des entrées invalides, le tableau est vide (l.89-101) et si aucunUWidgetComponentvalide ne reste sur l'acteur (l.106-125). GrepLPFocusWidgetComponentsurSource: seul ce fichier (l.127 et 147).- Moteur :
StaticAllocateObjectcherche un objet de même nom dans le même outer (E58\CoreUObject\Private\UObject\UObjectGlobals.cpp:3515-3516), le détruit (ConditionalBeginDestroy, l.3687-3691), boucle tant queIsReadyForFinishDestroyest faux (l.3693-3705), puis écrit l'avertissement (l.3706-3710).UPrimitiveComponent::IsReadyForFinishDestroyattendDetachFence(E58\Engine\Private\Components\PrimitiveComponent.cpp:2050-2054). - Ce que mesure « overwrite took » : le temps passé par le thread de jeu à attendre que le thread de rendu libère le proxy de l'ancien composant avant de reconstruire l'objet au même nom. Plus lourd en scène chargée (11,66 ms en scène de couple).
4. Verdict : confirmée
Mécanisme établi par le code. Qui détruit l'ancien composant : HideAllMarkers du Blueprint (estimé, LPMapMarkersGuardSubsystem.h:2 et absence de composant valide à la l.107).
Correctif proposé (C++, Src\LPMapMarkersGuardSubsystem.cpp:127) :
const FName FocusName = MakeUniqueObjectName(Markers, UWidgetComponent::StaticClass(), TEXT("LPFocusWidgetComponent"));
UWidgetComponent* Focus = NewObject<UWidgetComponent>(Markers, FocusName);
MakeUniqueObjectName a la même signature en 5.5 (D:\Game\Launcher\Engine\UE_5.5\Engine\Source\Runtime\CoreUObject\Public\UObject\UObjectGlobals.h:972) et en 5.8 (E58\CoreUObject\Public\UObject\UObjectGlobals.h:1062), donc pas de garde de version. La fonction boucle tant qu'un objet de ce nom existe et ne rend jamais le nom de base (UObjectGlobals.cpp:2715-2728) : plus de reconstruction par-dessus, l'ancien objet part au GC normal. Autre voie (Q1) : correctif Blueprint K8, puis retrait de la création du composant de focus (garder le vidage de Vector2Ds, l.104).
5. Hypothèse suivante
Aucune. Suite : IMPL N2 (1 ligne C++), BUILD, puis VAL en jeu ; attendu : 0 ligne overwrite took sur LPFocusWidgetComponent, ligne de garde slot de focus toujours présente, plus aucune lecture hors bornes de WidgetComponents après la première.
Constats
Tableau récapitulatif
| Clé | Famille (T1) | CIBLE / REF | Preuve (nœud ou source) | Pile (journal) | Cause | Verdict | Correctif proposé | Effort |
|---|---|---|---|---|---|---|---|---|
| K1 | StreetMap_Static_C:SearchByAmenitySafe |
9+1 / 14+1 | SearchByAmenitySafe.txt:11-19,175-179 ; GI__EventGraph.txt:11376-11393 |
CIBLE:7898-7910, 51374-51400 | CurrentCityExpansion None sans extension de ville, lu sans IsValid |
confirmée (forme nue : nœud incertain) | 2 IsValid (BP) |
faible |
| K2 | StreetMap_Static_C:ExecuteUbergraph_StreetMap_Static |
5 / 6 (+4) | StreetMap_Static__EventGraph.txt:5417-5515 |
CIBLE:7446-7462, 7741-7756 ; REF:8942 | BGA None ou détruit, lu 3 fois sans IsValid |
confirmée | 3 IsValid (BP) |
faible |
| K3 | Room_C:pickPresetWorld |
4 / 10 | Room__pickPresetWorld.txt:20-39 |
CIBLE:7465-7503, 7759-7791 ; preset CIBLE:7505 | rue sans polygone, BuildingPoints[0..1] sans test |
confirmée (tableau vide normal) | 1 Branch (BP) |
faible |
| K4 | GI_C:(Script Msg) Person_24 |
39 / 59 | GI__clearVariable.txt:5-24 |
CIBLE:38010-38022, 38063-38075 | variable sans personne, Person[0] sans test |
confirmée (même événement que GIVAR) | 1 Branch (BP, avec GIVAR) |
faible |
| K5 | GI_C:(Script Msg) Texture2dArray_3 |
6 / 0 | non localisé (Grep 0 dans les dumps GI) | CIBLE:51230, 51255 (sans pile) | lecture [0] d'un Te2dArray vide (estimé) |
indécise | IsValidIndex (à poser sur le nœud) |
dump N0 d'abord |
| K6 | SexInterface_C:(Script Msg) |
3 / 0 | non dumpé | CIBLE:51235-51240 (sans pile) | index fixes 2-4 pour 2 participants (estimé) | indécise | IsValidIndex ou boucle |
dump N0 d'abord |
| K7 | Person_C:(Script Msg) Standspots |
15 / 9 | Person__standIdle.txt:144-162,171-209 |
CIBLE:7633-7636, 19503-19625 | tableau parallèle creux (bSizeToFit) |
confirmée (bénin) | 1 Branch (BP) |
faible |
| K8 | GI_C:(Script Msg) WidgetComponents |
1 / 2 | GI__EventGraph.txt:13185-13212 ; LPMapMarkersGuardSubsystem.cpp:61,89-125 |
CIBLE:7380-7399, 7413 | lecture avant le tick de garde | confirmée | 1 Branch (BP) |
faible |
| K9 | hitch LPFocusWidgetComponent |
2 / 4 | LPMapMarkersGuardSubsystem.cpp:127 ; UObjectGlobals.cpp:3515-3710 |
CIBLE:7972, 51241 | NewObject à nom fixe sur un objet détruit non collecté |
confirmée | MakeUniqueObjectName (C++, 1 ligne) |
faible + BUILD |
Recompte (Grep count, une commande par clé, motifs cités dans chaque § 1) : CIBLE K1 9, K2 5, K3 4, K4 39, K7 15, K8 1, K9 2 ; K5 6 et K6 3 (lignes listées par Grep). REF K1 16, K2 10, K3 10 ; motif regroupé Script Msg: … array '(Person_24_|Standspots_Occupied|WidgetComponents|Texture2dArray_3_|SexPersons) = 70 = 59 + 9 + 2 + 0 + 0 (STA-T1-INV.md:121-123,134,143). Tous égaux aux comptes de STA-T1.
Clés non traitées ou partielles
- K5 : nœud non localisé (fonction
GInon dumpée) ; K6 :SexInterfacenon dumpé. Correctif générique seulement. - K1, forme nue (1 / 1) : même appel établi ; nœud exact non départagé.
- Hors périmètre, cités pour mémoire :
StreetMap_Static_C:findNearbyBuilding(REF 2, même clé que K1, même garde) ;Accessed NonedeclearVariable(GIVAR),OccupyingFntetNear(PERSON),CallFunc_Array_Get_Item_53(GIUBER) ;Divide by zero(SexAction_C, Room_C).
Établi / estimé / incertain
- Établi : nœuds et liens cités (dumps:ligne), piles (journal:ligne), comptes (Grep), code de la garde et mécanismes moteur (sources 5.8 installées), absence d'emplacement de ville (Glob).
- Estimé : noms des événements personnalisés (
PlayBGA,FocusOnMapMarkers,LoadCityExpansion) déduits des appels et des piles, car le dump ne nomme pas lesCustomEvent; destruction du composant de focus parHideAllMarkers; références nulles après le GC (K2) ; mécanismes K5 et K6. - Incertain : nœud de la forme nue (K1) ; fonction
GIde K5 ; fonctionSexInterfacede K6. Essais : dumps N0 indiqués en K5 et K6.
Questions pour l'utilisateur ou la SPEC
- Q1 (K8/K9) : garder la garde C++ et corriger seulement le nom (
MakeUniqueObjectName), ou corrigerFocusOnMapMarkersen Blueprint et retirer la création du composant de focus ? La première voie ne touche aucun Blueprint (principe deLPMapMarkersGuardSubsystem.h:4). - Q2 (K4) : une seule fiche IMPL pour
clearVariable(GIVAR + VILLE).
Compte rendu (sk-protocol § 3)
[sk-protocol] Skills dans le contexte : sk-protocol, ue-cpp-build, lp-commandlets, lp-paths.
- Résultat : partiel. 7 clés sur 9 ont une cause confirmée, une preuve et un correctif ; K5 et K6 restent indécises (nœud non localisé, faute de dump).
- Preuves : dumps
StreetMap_Static__SearchByAmenitySafe,StreetMap_Static__EventGraph,Room__pickPresetWorld,GI__clearVariable,GI__EventGraph,Person__standIdle;Src\LPMapMarkersGuardSubsystem.cpp/.h; moteur 5.8 (ScriptCore.cpp,KismetArrayLibrary.cpp,UObjectGlobals.cpp/.h,PrimitiveComponent.cpp) et 5.5 (UObjectGlobals.h:972). - Chiffres : Grep
countpar clé sur CIBLE et REF (§ Constats, recompte), tous égaux à STA-T1. - Incertitudes : K1 forme nue ; K5 et K6 ; noms des
CustomEvent(estimés). - Écarts : budget dépassé (≈ 58 appels d'outils contre ≈ 40 prévus, pic non mesuré) ;
MapMarkers_Cnon dumpé, donc lu au journal et dansSource\. Fichier écrit :D:\Game\LifePlay-master 5.5\Docs\Migration\etat\ST\STA\STA-T2b-VILLE-DIAG.md(seul). - Suite : l'orchestrateur doit lancer un N0 (dumps
GIcandidats pour K5,SexInterfacepour K6), trancher Q1 et Q2, puis passer K1-K4, K7-K9 à STA-T2c. État : diagnostic livré, aucune correction faite.