UE4 Equipamento para Multiplayer # 4 | Criando e conectando um contêiner


Neste artigo, discutiremos a criação de um componente de inventário e a conexão com o ator necessário. Como esse componente é simplesmente um repositório de objetos e a lógica de seu carregamento / descarregamento, não há diferença em aplicá-lo a um caractere ou algum tipo de caixa.


Você pode criar um componente usando o Blueprint e o C ++ . Eu prefiro o segundo método, pois vou usar ativamente a funcionalidade C ++ .




Primeiro, criamos uma estrutura de célula para armazenar um item. Prefiro armazená-lo em um arquivo .h separado para conectar-se livremente, quando necessário, onde necessário:


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

Sim, nossa célula de inventário contém apenas três variáveis: identificador, quantidade e parâmetros exclusivos. Nada mais. Todos os dados podem ser copiados, salvos e baixados sem problemas. Sem texturas, referências a atores etc. aqui não. Todas as informações adicionais podem ser baixadas do banco de dados no DataAsset , sobre o qual falamos anteriormente.


Provavelmente, você já notou outra estrutura StructItemFactors.h , conectada no início. Isso nada mais é do que um repositório de propriedades exclusivas do objeto (na forma de um flutuador ), como desgaste, dano, etc. Ou seja, propriedades que são inerentes apenas a esta cópia do assunto e nenhuma outra é a mesma. Essa estrutura é muito simples:


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 a pena notar uma função muito interessante na estrutura acima, projetada para simplificar bastante nossas vidas:


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

Isso nada mais é do que um operador de comparação == , que podemos usar para essa estrutura para não extrair elementos para isso toda vez. Muito confortável




Então, com as estruturas prontas. Prosseguimos com a criação do 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); /*        ,   ... */ }; 

Se no código acima, ative a linha


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

então você pode conectar esse componente diretamente ao Blueprint . Eu prefiro fazer isso em C ++ . Para Personagem, fica assim:


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

Bem, para um baú como este:


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

Como você pode ver, a diferença está apenas nos nomes das variáveis.




No próximo artigo, falarei sobre os recursos de replicação (simples nos dedos ), que tornarão nosso inventário verdadeiramente multijogador.

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


All Articles