该插件将物品分为可以变化的部分(
UArcItemStack
)与不变的部分(
ItemDefinition
)
一、
UArcItemStack
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
ItemName
StackSize
物品名和当前堆栈数量,最大堆栈数量由
UArcItemDefinition
保存
1.1.2、
ItemDefinition
ItemDefinition
物品实体资产,储存不变化和同步的核心信息,仅使用默认实例尽可能节省储存控件。
参考
:
ItemDefinition
1.1.3、
SubItemStacks
SubItemStacks
子物品堆栈,可以叠加防止子物品,和主物品一摸一样。
可以用于一个物品中储存子物品的情况。比如枪支和他的配件可以共享一个槽。
1.1.4、
Rarity
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
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
作用:
MaxStackSize
确定最大堆栈数,
OwnedTags
确定物品所属类别,这两个元素确定了物品在背包逻辑中的基本信息,供系统内部使用。
2.1.2、
WorldItemModel
与
UIData
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),是一个高科拓展的数据集合。