// Unreal Engine 5

PROJETS UNREAL ENGINE

Retrouvez ici l'avancement de mes projets Unreal Engine, leurs images et vidéos de démonstration, ainsi que les technologies utilisées.

Saprophages Demo

Saprophages Demo

Mouvements et drone

Saprophages Demo est une recréation de l'univers de mon jeu de rôle sur table, conçue comme un terrain d'expérimentation pour mes implémentations de gameplay. Cette première itération intègre le Game Animation Sample Project (GASP) afin d'obtenir des mouvements réalistes avec un modèle cohérent avec l'esthétique du jeu. J'y ai également ajouté un prototype de drone que le joueur peut posséder, contrôler et utiliser pour réaliser des interactions simples, comme ouvrir une porte.

Unreal Engine 5 GASP Possession Interactions

Saprophages Demo

Équipement et armes

Cette itération introduit le système d'équipement et l'utilisation d'armes par le personnage principal, dans un environnement plus immersif et proche de la direction artistique visée pour le jeu final. Le joueur peut équiper ou déséquiper une arme, viser, tirer, recharger et changer d'arme. Les caractéristiques des armes sont définies dans des assets de données, pour une architecture orientée data-driven.

Unreal Engine 5 Data Assets Data-Driven Système d'armes

Saprophages Demo

Traversals

Cette dernière itération enrichit les déplacements du personnage principal avec l'intégration de systèmes de traversal, afin de lui offrir davantage de liberté de mouvement. J'ai étudié leur fonctionnement dans le projet d'exemple GASP, puis les ai adaptés à mon environnement pour les activer aux emplacements souhaités.

Unreal Engine 5 GASP Traversal Gameplay

Item Generator

Ce générateur utilise les données des Chroniques d'Urum pour produire des objets aléatoires cohérents avec leur contexte. Les Data Assets et Data Tables définissent les objets, leurs qualités et leurs modificateurs, tandis que les Gameplay Tags relient les catégories, les règles de génération et les fragments associés.

Unreal Engine 5 C++ Data Assets Data Tables Gameplay Tags Génération procédurale
18types de modificateurs applicables selon l'objet
13types d'objets aux effets uniques selon les jets
7niveaux de rareté
272ingrédients et potions d'apothicaire
78types d'armes
54types d'armures
38types de gemmes
96runes aux effets magiques uniques

Générer l'objet à partir du contexte

ItemGeneratorComponent choisit d'abord une qualité, puis sélectionne le type d'objet à générer dans une table pondérée associée au lieu. Il assemble ensuite les fragments et calcule le poids total de l'instance obtenue.

UGeneratedItemInstance* UItemGeneratorComponent::CreateItem(const FGameplayTag Location)
{
    UGeneratedItemInstance* NewItem = NewObject<UGeneratedItemInstance>(this);

    ItemQualityData = GetItemQuality();
    NewItem->QualityTag = ItemQualityData.ItemQualityTag;
    NewItem->ItemColor = ItemQualityData.QualityColor;
    NewItem->Rolls = ItemQualityData.Rolls;

    NewItem->ItemTypeTag = GetItemTypeFromLocation(Location);
    AddFragmentsFromTags(NewItem, NewItem->ItemTypeTag);
    CalculateItemTotalBurden(NewItem);

    return NewItem;
}

Assembler une instance composée de fragments

GeneratedItemInstance est l'objet final retourné par le générateur. Il conserve l'identité de l'objet, sa qualité, ses modificateurs et la collection de fragments qui portent ses propriétés de gameplay.

UCLASS(BlueprintType)
class URUM_PROTO_API UGeneratedItemInstance : public UObject
{
    GENERATED_BODY()

public:
    FGameplayTag ItemTypeTag;
    FGameplayTag QualityTag;
    FGameplayTagContainer ModifierTags;
    FString ItemName;
    float ItemBurden = 0.f;
    FLinearColor ItemColor = FLinearColor::White;
    int32 Rolls = 0;

    UPROPERTY(BlueprintReadOnly, Instanced)
    TArray<TObjectPtr<UItemFragment>> Fragments;
};

Fragment de base et modificateurs

Une règle associe le tag de l'objet à sa classe de fragment de base. Ce fragment récupère les données de la catégorie concernée, par exemple les dégâts, la résistance et la portée d'une arme. Selon la rareté, des jets supplémentaires sélectionnent des Modifier Fragments compatibles dans un pool pondéré, sans dupliquer un modificateur déjà appliqué.

void UItemGeneratorComponent::CreateModifierFragments(
    UGeneratedItemInstance* ItemInstance, const FGameplayTag ItemTag) const
{
    int32 Rolls = GetModifiersRollsAmount(ItemInstance->QualityTag, ItemTag);
    TArray<FModifierPoolRow> PoolRows =
        GetEligibleModifierRows(ItemInstance->QualityTag, ItemTag);

    while (Rolls > 0 && PoolRows.Num() > 0)
    {
        FModifierPoolRow RandomRow;
        GetRandomModifierRow(PoolRows, RandomRow);

        if (ItemInstance->ModifierTags.HasTagExact(RandomRow.ModifierFragmentTag))
        {
            continue;
        }

        InitializeFragmentFromPoolRow(ItemInstance, RandomRow);
        PoolRows.RemoveAll([&](const FModifierPoolRow& Row)
        {
            return Row.ModifierFragmentTag == RandomRow.ModifierFragmentTag;
        });

        Rolls--;
    }
}

Qualité magique et jets de modificateurs

Cette définition de qualité magique applique une couleur distinctive et des ajustements de statistiques à l'objet généré. Elle garantit d'abord un Modifier Fragment, puis peut en ajouter d'autres grâce à une série de probabilités dégressives : 38 %, 25 %, 8 %, puis 4 %.

Définition Unreal Engine de la qualité magique avec ses statistiques et ses chances de jets de modificateurs
Qualité Item.Rarity.Magic Modificateurs garantis 1 Chances supplémentaires 38 % / 25 % / 8 % / 4 % Bonus de dégâts +3 Multiplicateur de résistance ×2 Nombre de jets 3

Le générateur commence donc avec le modificateur garanti. Il lance ensuite un premier jet à 38 % pour en ajouter un autre, puis un second à 25 % seulement si le premier réussit, et ainsi de suite. La séquence s'arrête immédiatement dès qu'un jet échoue : un échec au jet à 25 %, par exemple, empêche les jets à 8 % et 4 %. Cette progression dégressive limite naturellement le nombre de modificateurs tout en laissant une chance aux objets exceptionnels.

Exemple : une arme magique liée

Cet exemple illustre une génération possible. Dans un lieu où les armes peuvent apparaître, le tirage sélectionne une arme de mêlée, puis une qualité qui accorde au moins un jet de modificateur. Le pool compatible propose le tag Item.Modifier.Bonded : le fragment correspondant complète alors l'arme avec ses propriétés de lien.

1. Contexte Lieu de génération LocationTag
2. Tirage pondéré Type d'objet Item.Type.Weapon.Melee.Blade
3. Données de base Weapon Fragment Dégâts, résistance, portée, poids
4. Rareté Qualité tirée Couleur, bonus et nombre de jets
5. Modificateur Bonded Fragment Item.Modifier.Bonded
6. Instance finale Arme magique liée Fragments + tags + poids total

Le WeaponFragment applique les valeurs de base et les ajustements de qualité. Un fragment Bonded signifie que l'objet est lié à son porteur : il peut revenir à portée de main dans une limite de distance définie, et son utilisateur peut sentir sa présence à une distance configurée. Ces fragments sont conservés ensemble dans GeneratedItemInstance, qui constitue la représentation complète de l'objet.

// Le fragment d'arme applique les donnees de base et la qualite.
TotalDamage = FMath::Max(1, BaseDamage + ItemQualityData.DamageModifier);
TotalResistance = BaseResistance * ItemQualityData.ResistanceMultiplier;

// Le modificateur Bonded ajoute ses proprietes specialisees.
BondReturnDistance = BondedBaseData.BondReturnDistance;
BondPresenceDetectionDistance = BondedBaseData.BondPresenceDetectionDistance;

Exemple de définition : Épée longue

Cette entrée de Data Asset décrit une épée longue avant sa génération. Son Gameplay Tag Item.Type.Weapon.Melee.Blade.LongSword permet au générateur d'identifier sa catégorie et d'instancier le WeaponFragment approprié. Les statistiques indiquées constituent les valeurs de base, auxquelles la qualité et les modificateurs peuvent ensuite s'ajouter.

Définition Unreal Engine d'une épée longue : tag, dégâts, résistance, prérequis, portée et poids
Type Arme à une main Dégâts de base 10 Résistance de base 10 Prérequis Force 3 / Agilité 3 Portée Mêlée Poids de base 10

Vers une présentation visuelle des objets

L'objectif du projet est d'exploiter au maximum les Gameplay Tags afin de construire un système data-driven, extensible à volonté sans multiplier les cas particuliers dans le code. La prochaine étape donnera une dimension plus visuelle au générateur, avec une animation de type loot box et une interface dédiée à la présentation des objets obtenus. À terme, chaque objet disposera de son propre rendu 3D et de VFX déterminés par ses caractéristiques, sa qualité et ses modificateurs.