UE4 | Équipement pour multijoueur # 4 | Création et connexion d'un conteneur


Dans cet article, nous allons discuter de la création d'un composant d'inventaire et de sa connexion à l'acteur requis. Étant donné que ce composant est simplement un référentiel d'objets et la logique de leur chargement / déchargement, il n'y a aucune différence dans son application à un personnage ou à une sorte de boîte.


Vous pouvez créer un composant en utilisant Blueprint et C ++ . Je préfère la deuxième méthode, car je vais utiliser activement la fonctionnalité C ++ .




Tout d'abord, nous créons une structure de cellules pour stocker un élément. Je préfère le stocker dans un fichier .h séparé afin de me connecter librement si nécessaire, si nécessaire:


StructContainerStack.h
/// Copyright 2018 Dreampax Games, Inc. All Rights Reserved. /* Struct for Container Stack. This file is used as #include */ #pragma once /* Includes from Engine */ #include "GameplayTagContainer.h" /* Includes from Dreampax */ #include "Data/StructItemFactors.h" #include "StructContainerStack.generated.h" /* Declaration for contaiter stack structure. BlueprintType required to use in BP */ USTRUCT(BlueprintType) struct FContainerStack { GENERATED_USTRUCT_BODY() /* Gameplay tag to store the name */ UPROPERTY(EditAnywhere) FGameplayTag ItemNameTag; UPROPERTY(EditAnywhere) int ItemAmount; /* Specific factors such as durability, damage etc. */ UPROPERTY(EditAnywhere) TArray <FItemFactor> ItemFactors; FContainerStack() { Clear(); } void Clear() { ItemNameTag.FromExportString("NAME_None"); ItemAmount = 0; ItemFactors.Empty(); } FORCEINLINE FGameplayTag GetItemNameTag() const { return ItemNameTag; } void SetItemNameTag(FGameplayTag const & ItemNameTagNew) { if (ItemNameTagNew.IsValid()) { ItemNameTag = ItemNameTagNew; } else { Clear(); } } FORCEINLINE int GetItemAmount() const { return ItemAmount; } void SetItemAmount(int const & ItemAmountNew) { if (ItemAmountNew > 0) { ItemAmount = ItemAmountNew; } else { Clear(); } } FORCEINLINE TArray<FItemFactor> * GetItemFactors() { return &ItemFactors; } void SetItemFactors(TArray<FItemFactor> const & ItemFactorsNew) { if (ItemFactorsNew.Num() > 0) { ItemFactors = ItemFactorsNew; } } }; 

Oui, notre cellule d'inventaire ne contient que 3 variables: identifiant, quantité et paramètres uniques. Rien de plus. Toutes les données peuvent être copiées, enregistrées et téléchargées sans aucun problème. Pas de textures, de références aux acteurs , etc. pas ici. Toutes les informations supplémentaires peuvent être téléchargées à partir de la base de données sur le DataAsset , dont nous avons parlé plus tôt.


Vous avez probablement déjà remarqué une autre structure StructItemFactors.h , connectée au début. Ce n'est rien de plus qu'un référentiel de propriétés uniques de l'objet (sous la forme d'un flotteur ), telles que l'usure, les dommages, etc. Autrement dit, des propriétés inhérentes uniquement à cette copie du sujet, et aucune autre n'est la même. Cette structure est très simple:


StructItemFactors.h
 /// Copyright 2018 Dreampax Games, Inc. All Rights Reserved. /* Struct for Factors. This file is used as #include */ #pragma once /* Includes from Engine */ #include "GameplayTagContainer.h" /* Includes from Dreampax */ // no includes #include "StructItemFactors.generated.h" USTRUCT(BlueprintType) struct FItemFactor { GENERATED_USTRUCT_BODY() /* Name of Item Attribute Factor */ UPROPERTY(EditDefaultsOnly, Category = "ItemsDatabase") FGameplayTag ItemFactorTag; /* Factor for the Item Attribute */ UPROPERTY(EditDefaultsOnly, Category = "ItemsDatabase") float ItemFactor; /* for this type to be comparable */ friend bool operator==(const FItemFactor & Lhs, const FItemFactor & Rhs) { return Lhs.ItemFactorTag == Rhs.ItemFactorTag && Lhs.ItemFactor == Rhs.ItemFactor; } FItemFactor() { Clear(); } void Clear() { ItemFactorTag.EmptyTag; ItemFactor = 0; } FORCEINLINE FGameplayTag GetItemFactorTag() { return ItemFactorTag; } void SetItemFactorTag(FGameplayTag const &ItemFactorTagNew) { if (ItemFactorTagNew.IsValid()) { ItemFactorTag = ItemFactorTagNew; } else { Clear(); } } FORCEINLINE float GetItemFactor() { return ItemFactor; } void SetItemFactor(float const & ItemFactorNew) { if (ItemFactorNew > 0.0f) { ItemFactor = ItemFactorNew; } else { Clear(); } } }; 

Il convient de noter une fonction très intéressante dans la structure ci-dessus, qui est conçue pour simplifier considérablement nos vies:


 friend bool operator==(const FItemFactor & Lhs, const FItemFactor & Rhs) { return Lhs.ItemFactorTag == Rhs.ItemFactorTag && Lhs.ItemFactor == Rhs.ItemFactor; } 

Ce n'est rien de plus qu'un opérateur de comparaison == , que nous pouvons utiliser pour cette structure afin de ne pas en extraire à chaque fois des éléments. Très confortable.




Donc, avec les structures terminées. Nous procédons à la création du composant:


DreampaxContainerComponent.h
 /// Copyright 2018 Dreampax Games, Inc. All Rights Reserved. #pragma once /* Includes from Engine */ #include "Components/ActorComponent.h" #include "GameplayTagContainer.h" /* Includes from Dreampax */ #include "Data/StructItemFactors.h" #include "Data/StructContainerStack.h" #include "DreampaxContainerComponent.generated.h" //UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) // currently not required UCLASS() class DREAMPAX_API UDreampaxContainerComponent : public UActorComponent { GENERATED_BODY() private: UPROPERTY(Transient, Replicated, EditAnywhere, Category = "Container") TArray<FContainerStack> ContentOfContainer; public: /* Sets default values for this component's properties */ UDreampaxContainerComponent(const FObjectInitializer & ObjectInitializer); /*        ,   ... */ }; 

Si dans le code ci-dessus, activez la ligne


 UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) 

vous pouvez ensuite connecter ce composant directement à Blueprint . Je préfère le faire en C ++ . Pour Caractère, cela ressemble à ceci:


 Inventory = CreateDefaultSubobject<UDreampaxContainerComponent>(TEXT("Inventory")); 

Eh bien, pour un coffre comme celui-ci:


 ADreampaxActorContainer::ADreampaxActorContainer(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { Container = CreateDefaultSubobject<UDreampaxContainerComponent>(TEXT("Container")); } 

Comme vous pouvez le voir, la différence ne concerne que les noms des variables.




Dans le prochain article, je parlerai des fonctionnalités de réplication (simple sur les doigts ), ce qui rendra notre inventaire vraiment multijoueur.

Source: https://habr.com/ru/post/fr420115/


All Articles