Files
Unreal_EmberWild/.claude/CLAUDE.md
T
Mathew ed7c7fd991 Import initial du projet Survival (UE 5.8)
Boucle de jeu complète : récolte, inventaire, consommation, stats de survie,
mort et respawn. Gameplay en C++, Blueprints réservés au câblage d'assets.

Assets binaires (.uasset, .umap, textures, audio) suivis via Git LFS.
Binaries/, Intermediate/, Saved/ et DerivedDataCache/ sont ignorés :
régénérés au build, ils pèsent 3 Go pour 1,3 Go de contenu utile.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 11:29:07 +02:00

6.3 KiB

Survival_projet — Unreal Engine 5.8

Jeu de survie solo à la première personne, gameplay écrit en C++, Blueprints réservés au câblage d'assets. Inspirations assumées : Raft, Aloft, Valheim, esthétique solarpunk. Assets d'environnement : pack SoStylized (sa végétation n'est pas à l'échelle humaine).

Interlocuteur

L'auteur vient de Unity et découvre Unreal. Il écrit en français — répondre en français.

Faire systématiquement le parallèle Unity quand un concept nouveau apparaît (Blueprint ≈ prefab, DataAsset ≈ ScriptableObject, ActorComponent ≈ MonoBehaviour, BeginPlay ≈ Start, Trace Channel ≈ LayerMask). Il raisonne déjà très bien en composants, inutile de réexpliquer les bases.

Signaler en revanche les endroits où le modèle diverge réellement de Unity, ce sont ceux qui le piègent : framework GameMode/Controller/Pawn imposé, UPROPERTY obligatoire pour le GC, constructeur qui tourne dans l'éditeur (CDO), pas de matrice de collision globale.

Il valide les décisions de design lui-même. Proposer une recommandation argumentée, pas un catalogue d'options. Quand un choix change matériellement le code (modèle d'inventaire, règles de mort), demander avant de coder plutôt que de deviner.

Compiler

& "C:\Program Files\Epic Games\UE_5.8\Engine\Build\BatchFiles\Build.bat" Survival_projetEditor Win64 Development -Project="d:\Projet\Perso\Unreal\Survival_projet\Survival_projet.uproject" -WaitMutex
  • Un DLL nommé UnrealEditor-Survival_projet-000N.dll signifie que l'éditeur était ouvert : c'est un hot reload. Prévenir l'auteur de fermer et relancer l'éditeur.
  • -Rebuild échoue tant que l'éditeur tourne (DLL verrouillés).
  • Ne jamais réécrire en masse les timestamps des fichiers source pour forcer un build.
  • L'outil Edit renvoie parfois EPERM sur FpsPlayer.cpp (watcher qui tient le handle) : réessayer, ou passer par Write sur le fichier entier.

Règles d'architecture établies

Un système = un UActorComponent. Jamais de logique empilée dans AFpsPlayer, qui n'est qu'un assemblage de composants plus la caméra et le déplacement.

Où va quoi — le critère est « si le pawn meurt, est-ce que ça doit survivre ? » :

Nature Emplacement
Le corps : déplacement, caméra, inventaire, stats, interaction Pawn
Le joueur : widgets HUD, input d'interface (Tab, Q, hotbar) PlayerController
Les règles de la partie, le respawn GameMode
Ce que les autres savent de toi (plus tard, si multi) PlayerState

Données vs état. UItemDataAsset décrit ce qu'un objet est (nom, mesh, icône, effets). Quantité, charges restantes, durabilité sont de l'état et vivent sur le slot ou l'acteur. Mettre de l'état dans un DataAsset le partagerait entre toutes les instances du jeu.

Un Blueprint par comportement, un DataAsset par objet. 200 objets et 3 comportements donnent 3 Blueprints et 200 DataAssets. BP_Pickup est générique, son ItemData change par instance.

Réglages exposés. Toute valeur qui se règle à l'œil est une UPROPERTY(EditAnywhere), pour itérer en PIE sans recompiler.

Pièges C++ Unreal rencontrés : ne pas nommer un membre Player, OldPawn, Slot ou CrouchedEyeHeight dans une classe dérivée du moteur (masquage → erreur C4458 / UHT). TWeakObjectPtr ne permet pas de détecter une transition par simple comparaison de pointeurs, il faut un booléen d'état à côté.

Systèmes en place

Système Fichiers
Personnage, caméra, game feel FpsPlayer.h/.cpp
HUD, input d'interface, fondus, respawn FpsPlayerController.h/.cpp
Interaction (trace + interface) Interactable.h, InteractionComponent, InteractionPromptWidget
Objets ItemDataAsset, PickupItem
Inventaire InventoryComponent, InventoryWidget, InventorySlotWidget, HotbarWidget, InventoryDragDropOperation
Survie SurvivalStatsComponent, SurvivalStatsWidget

Décisions de gameplay figées

  • Inventaire : un seul TArray de 30 slots. Index 0-9 = barre rapide, 10-29 = grille. Conteneurs indépendants (un objet dans la barre n'apparaît pas dans la grille), même tableau uniquement pour que le glisser-déposer n'ait aucune conversion d'index à faire.
  • Ramassage : complète les piles existantes partout, puis ouvre un slot dans la barre en priorité, puis déborde dans la grille.
  • Glisser : normal = pile entière, Maj = moitié arrondie au supérieur, Ctrl = un seul. Lâcher hors de la grille jette au sol ; lâcher entre deux cases est absorbé (jamais de perte accidentelle).
  • Clic gauche = utiliser l'objet actif de la barre. Bindé sur le pawn, donc muet quand l'inventaire est ouvert — le conflit avec le drag & drop se règle tout seul.
  • Objets à charges (MaxUses > 1) ne s'empilent jamais. Les valeurs de restauration s'appliquent par utilisation. L'usure suit l'objet jusqu'au sol et revient avec lui.
  • Mort : tout tombe au sol autour du corps, respawn au PlayerStart, jauges pleines.
  • Fondus : un unique voile plein écran WBP_Fade au ZOrder 1000. Fondre widget par widget est fragile — les cases réécrivent leur propre RenderOpacity.
  • Après un respawn, le pawn est un nouvel acteur : les widgets doivent se rebrancher via BindToOwningPawn(), appelé depuis OnPossess.

Conventions

  • Commentaires en français. Ils expliquent le pourquoi et les pièges, jamais le quoi.
  • Nommage éditeur : BP_ acteurs, WBP_ widgets, DA_ data assets, IA_ input actions, IMC_ mapping contexts, GM_ game mode.
  • Widgets : classe C++ Abstract pour la logique, Widget Blueprint enfant pour la mise en page. Les widgets liés utilisent meta = (BindWidget), ou BindWidgetOptional quand l'élément est décoratif.
  • Les widgets s'abonnent à des délégués, jamais de Tick pour lire un état.

État actuel et suite

Boucle complète : récolter → ranger → consommer → survivre → mourir → réapparaître.

Prochaine étape recommandée : spawner de ressources avec repousse (AResourceSpawner, liste pondérée de DataAssets, rayon, densité, délai). Sans lui la carte se vide en dix minutes.

Ensuite, par ordre de valeur : craft, objet visible en main, coffres, sauvegarde, cycle jour/nuit.