UE4 | 多人游戏设备#4 | 创建和连接容器


在本文中,我们将讨论如何创建清单组件并将其连接到所需的Actor。 由于该组件只是对象的存储库及其加载/卸载的逻辑,因此将其应用于角色或某种盒子没有区别。


您可以使用BlueprintC ++创建组件。 我倾向于第二种方法,因为我将积极使用C ++功能。




首先,我们创建一个用于存储一项的单元格结构。 我更喜欢将其存储在单独的.h文件中,以便在必要时在必要时自由连接:


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

是的,我们的库存单元格仅包含3个变量:标识符,数量和唯一参数。 没什么 可以复制,保存和下载所有数据,没有任何问题。 没有纹理,对Actor的引用等。 不在这里 可以从DataAsset的数据库中下载所有其他信息,我们之前已经讨论过。


您很可能已经注意到另一个StructItemFactors.h结构,该结构在开始时已连接。 这仅是对象的任何唯一属性(以float形式)(例如磨损,损坏等)的存储库。 也就是说,仅此主题副本具有固有的属性,其他属性都不相同。 这个结构很简单:


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

值得注意的是,上面的结构中有一个非常有趣的功能,该功能旨在大大简化我们的生活:


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

这只不过是一个比较运算符== ,我们可以将其用于此结构,以免每次都提取元素。 很舒服




这样,结构完成。 我们继续创建该组件:


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); /*        ,   ... */ }; 

如果在上面的代码中激活该行


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

然后您可以将此组件直接连接到Blueprint 。 我更喜欢在C ++中执行此操作。 对于Character,它看起来像这样:


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

好吧,对于这样的箱子:


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

如您所见,区别仅在于变量的名称。




在下一篇文章中,我将讨论复制的功能( 手指简单),这将使我们的清单真正成为多人游戏。

Source: https://habr.com/ru/post/zh-CN420115/


All Articles