该插件将物品分为可以变化的部分(UArcItemStack )与不变的部分(ItemDefinition )
一、UArcItemStack
用于储存具体物品、物品当前堆叠数量、品质,子物品
1.1、属性
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Item", ReplicatedUsing=OnRep_Rarity)
UArcItemRarity* Rarity;
UPROPERTY(EditInstanceOnly, BlueprintReadWrite, Category="UI", ReplicatedUsing=OnRep_ItemName)
FText ItemName;
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Item", ReplicatedUsing=OnRep_ItemDefinition)
TSubclassOf<UArcItemDefinition_New> ItemDefinition;
UPROPERTY(Replicated)
FArcSubItemStackArray SubItemStacks;
UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = "Item", ReplicatedUsing=OnRep_StackSize)
int32 StackSize;
1.1.1、ItemName 和StackSize
物品名和当前堆栈数量,最大堆栈数量由UArcItemDefinition 保存
1.1.2、ItemDefinition
物品实体资产,储存不变化和同步的核心信息,仅使用默认实例尽可能节省储存控件。 参考:ItemDefinition
1.1.3、SubItemStacks
子物品堆栈,可以叠加防止子物品,和主物品一摸一样。 可以用于一个物品中储存子物品的情况。比如枪支和他的配件可以共享一个槽。
1.1.4、Rarity
物品价值/品质 虽然继承自UPrimaryDataAsset ,但是并没有设置AssetID
UArcItemRarity 的实现:
UCLASS(BlueprintType)
class ARCINVENTORY_API UArcItemRarity : public UPrimaryDataAsset, public IGameplayTagAssetInterface
{
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Rarity")
FGameplayTagContainer RarityTags;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Rarity")
FGameplayTagContainer TagsGrantedToItem;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Rarity")
FText RarityName;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Rarity")
FLinearColor RarityColor;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Instanced, Category= "Rarity")
UArcItemRarity_UserData* UserData;
};
参数: RarityName : 品质名(普通、传奇、超凡) RarityColor : 品质对应的颜色(白色、紫色、金色) RarityTags : 品质自身标签 TagsGrantedToItem : 品质给物品的标签(用于通过标签标记物品品质?) UserData : 目前为空UObject
1.2、接口
virtual bool HasValidItemData() const;
virtual bool CanStackWith(UArcItemStack* OtherStack) const;
virtual bool MergeItemStacks(UArcItemStack* OtherStack);
virtual UArcItemStack* SplitItemStack(int32 SplitAmount);
virtual bool CanAttachTo_Implementation(UArcItemStack* OtherStack);
virtual bool AddSubItemStack(UArcItemStack* SubItemStack);
virtual bool RemoveSubItemStack(UArcItemStack* SubItemStack);
virtual UArcItemStack* QueryForSubItem(const FGameplayTagQuery& StackQuery);
static void TransferStackOwnership(UArcItemStack*& ItemStack, AActor* Owner);
二、ItemDefinition
作用: 用于储存数据的DataAsset,但并没有继承自UPrimaryDataAsset ,而是自己重写GetPrimaryAssetId 以及实现IGameplayTagAssetInterface 来达到DataAsset效果 分为: 数据(最大堆叠大小、Tag)、 显示(模型与UI数据为)、逻辑(默认堆栈类)三个部分
2.1、属性
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Gameplay")
int32 MaxStackSize;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tags)
FGameplayTagContainer OwnedTags;
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Display")
UStaticMesh* WorldItemModel;
UPROPERTY(EditDefaultsOnly, Instanced, BlueprintReadWrite, Category = "UI", Meta = (AssetBundles = "UI"))
UArcUIData_ItemDefinition* UIData;
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Gameplay")
TSubclassOf<UArcItemStack> DefaultItemStackClass;
2.1.1、MaxStackSize 和OwnedTags
作用: MaxStackSize 确定最大堆栈数,OwnedTags 确定物品所属类别,这两个元素确定了物品在背包逻辑中的基本信息,供系统内部使用。
2.1.2、WorldItemModel 与UIData
作用: WorldItemModel 负责3D控件的展示,UIData 负责2D展示,构成物品的视觉显示部分。对于没有想过制作模型的Item也可以通过设置一个基本模型来替代,但这种方式并不是太理想,可以和UIData 一样做一个ModelData来的。 UArcUIData_ItemDefinition :
UCLASS(Blueprintable, Abstract, BlueprintType)
class ARCINVENTORY_API UArcUIData_ItemDefinition : public UArcInvUIData{
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = UI)
TSubclassOf<UArcInventoryBaseItemCardWidget> SmallItemCard;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = UI)
TSubclassOf<UArcInventoryBaseItemCardWidget> ItemTooltip;
};
SmallItemCard :插槽UI的显示 ItemTooltip :放在UI上时出现的提示 UArcInvUIData :继承自UObject的空类
2.1.3、DefaultItemStackClass
确定默认的栈Class,可以在ArcInventoryComponent 中看到,物品的交换是基于栈的交换。可以通过设置栈的类型来轻易控制栈的行为逻辑。
2.2、接口
virtual void GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const override;
virtual FPrimaryAssetId GetPrimaryAssetId() const override;
GetOwnedGameplayTags 用于方便查找物品Tag,详情:GameplayTags GetPrimaryAssetId 用于供AssetManager 使用与查找,详情:Asset Management
2.3、总结:
作为DataAsset,同时储存资产的数据、表现与逻辑,涵盖了一个物品所需的所有方向,且每个方向都可以进行拓展(除了WorldItemModel 被定死为UStaticMesh ),可以说是一份很棒的数据驱动指导。
三、总结
目前共有五个核心类: UArcInventoryComponent 、FArcInventoryItemSlot 、UArcItemStack 、ItemDefinition 、FArcInventoryItemSlotReference 可以分为: 背包插槽:UArcInventoryComponent 、FArcInventoryItemSlot 与FArcInventoryItemSlotReference 物品数据:UArcItemStack 与ItemDefinition
解耦方式简单易懂:加中间件(FArcInventoryItemSlotReference )+分隔变与不变的部分(UArcItemStack 与ItemDefinition ),符合设计模式的基本原则
4.1、物品数据
物品中变化的部分都被放入UArcItemStack ,而不变的部分则放入ItemDefinition 中。
UArcItemStack 作为物品实例,名字Tag、品质和实体指针,极其轻度的设计给所有基于Stack的操作与网络同步都快捷无比。
ItemDefinition 是真正储存数据的地方,而大部分数据并不会被更改,所以只需要知道ItemDefinition 的类名并获取默认对象就行,可以把他看作是常量部分。其控制了物品的所有关键数据(数据、表现、逻辑MVC),是一个高科拓展的数据集合。
|