UE4 | Equipo para Multijugador # 4 | Crear y conectar un contenedor


En este artículo, analizaremos la creación de un componente de inventario y su conexión con el actor requerido. Dado que este componente es simplemente un repositorio de objetos y la lógica de su carga / descarga, no hay diferencia en aplicarlo a un personaje o algún tipo de cuadro.


Puede crear un componente utilizando Blueprint y C ++ . Prefiero el segundo método, ya que voy a utilizar activamente la funcionalidad de C ++ .




En primer lugar, creamos una estructura celular para almacenar un elemento. Prefiero almacenarlo en un archivo .h separado para conectarlo libremente cuando sea necesario donde sea necesario:


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; } } }; 

Sí, nuestra celda de inventario contiene solo 3 variables: identificador, cantidad y parámetros únicos. Nada mas. Todos los datos se pueden copiar, guardar y descargar sin ningún problema. Sin texturas, referencias a actores , etc. no aqui Toda la información adicional se puede descargar de la base de datos en el DataAsset , del que hablamos anteriormente.


Lo más probable es que ya haya notado otra estructura StructItemFactors.h , conectada al principio. Esto no es más que un repositorio de propiedades únicas del objeto (en forma de flotador ), como desgaste, daño, etc. Es decir, propiedades que son inherentes solo a esta copia del tema, y ​​ninguna otra es igual. Esta estructura es muy 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(); } } }; 

Vale la pena señalar una función muy interesante en la estructura anterior, que está diseñada para simplificar enormemente nuestras vidas:


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

Esto no es más que un operador de comparación == , que podemos usar para esta estructura para no extraer elementos para esto cada vez. Muy comodo




Entonces, con las estructuras terminadas. Procedemos a la creación del componente:


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 en el código de arriba activa la línea


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

entonces puede conectar este componente directamente a Blueprint . Prefiero hacer esto en C ++ . Para Carácter, se ve así:


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

Bueno, para un cofre como este:


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

Como puede ver, la diferencia está solo en los nombres de las variables.




En el próximo artículo hablaré sobre las características de la replicación (simple en los dedos ), lo que hará que nuestro inventario sea realmente multijugador.

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


All Articles