Documentation
1.创建背包组件.md
2025/12/16预计阅读 13 分钟
创建一个背包组件
继承ActorComponent组件

创建背包相关模型
FMyBackpackItem - 物品静态数据
USTRUCT(BlueprintType)
struct FMyBackpackItem : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="id")
FName Id;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="名字")
FText Name;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="材质")
UTexture* TexTure;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="初始数量")
int32 InitCount;
FMyBackpackItem(): Id("Id"), TexTure(), InitCount(0)
{
Name = FText::FromString(TEXT("物品名称"));
}
};
FMyBackpackData - 物品数据
USTRUCT(BlueprintType)
struct FMyBackpackData
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="物品数据")
FMyBackpackItem ItemData;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="物品数量")
int32 ItemNum;
FMyBackpackData(): ItemNum(0)
{
}
};
FMyBackpack - 背包
USTRUCT(BlueprintType)
struct FMyBackpack
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="物品列表")
TArray<FMyBackpackData> Items;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="背包ID")
FText Id;
FMyBackpack()
{
Id = FText::FromString(TEXT("默认背包"));
}
};
添加背包模型到组件
它是受保护的,不能随意在蓝图中对它进行操作
protected:
UPROPERTY(DisplayName="背包组件", BlueprintReadOnly)
FMyBackpack Backpack;
完整的代码
MyBackpackComponent.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "MyBackpackComponent.generated.h"
USTRUCT(BlueprintType)
struct FMyBackpackItem : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="id")
FName Id;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="名字")
FText Name;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="材质")
UTexture2D* TexTure;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="初始数量", meta=(ClampMin=0))
int32 InitCount;
FMyBackpackItem(const FName ItemId): Id(ItemId), TexTure(), InitCount(10)
{
Name = FText::FromString(TEXT("梁典典的物品"));
}
FMyBackpackItem(): FMyBackpackItem("Id")
{
}
//生成测试数据列表
static TArray<FMyBackpackItem> MakeTestDataArr();
};
USTRUCT(BlueprintType)
struct FMyBackpackData
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="物品数据")
FMyBackpackItem ItemData;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="物品数量")
int32 ItemNum;
FMyBackpackData(): ItemNum(0)
{
}
//从静态数据生成物品item
static FMyBackpackData FromItem(const FMyBackpackItem& Item);
};
USTRUCT(BlueprintType)
struct FMyBackpack
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="物品列表")
TArray<FMyBackpackData> Items;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="背包ID")
FText Id;
FMyBackpack()
{
Id = FText::FromString(TEXT("默认背包"));
}
};
UCLASS(Blueprintable, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class DEMO2_API UMyBackpackComponent : public UActorComponent
{
GENERATED_BODY()
public:
UMyBackpackComponent();
//初始化背包数据
UFUNCTION(BlueprintCallable, DisplayName="初始化背包数据", Category="背包函数")
void InitBackpackData(TArray<FMyBackpackItem> NewItemDataArr);
//生成测试的物品
UFUNCTION(BlueprintCallable, DisplayName="初始化测试物品数据", Category="背包函数")
void AddTestData();
//添加物品
UFUNCTION(BlueprintCallable, DisplayName="向背包添加物品", Category="背包函数")
void AddItem(FMyBackpackItem NewItem);
//移除物品
UFUNCTION(BlueprintCallable, DisplayName="移除背包的某个物品", Category="背包函数")
void RemoveItem(FMyBackpackItem Item);
//移除物品(Id)
UFUNCTION(BlueprintCallable, DisplayName="通过ID来移除某个物品", Category="背包函数")
void RemoveItemByName(FName ItemId);
//重置背包
UFUNCTION(BlueprintCallable, DisplayName="清空重置背包", Category="背包函数")
void CleanBackpack();
//==============================================================动态委托============================================
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOneParamAdded, FMyBackpackData, Item);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOneParam, FMyBackpackData, Item);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCleanBackpack);
UPROPERTY(BlueprintAssignable, BlueprintCallable, DisplayName="当物品添加成功时调用", Category="背包Delegate")
FOneParamAdded OnItemAdded;
UPROPERTY(BlueprintAssignable, BlueprintCallable, DisplayName="当物品被移除成功时", Category="背包Delegate")
FOneParam OnItemRemoved;
UPROPERTY(BlueprintAssignable, BlueprintCallable, DisplayName="当清空背包时调用", Category="背包Delegate")
FCleanBackpack OnCleanBackpack;
protected:
//开始游戏
virtual void BeginPlay() override;
//背包数据
UPROPERTY(DisplayName="背包数据", BlueprintReadOnly)
FMyBackpack Backpack;
public:
//获取背包对象
FMyBackpack GetBackpack();
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
};
MyBackpackComponent.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyBackpackComponent.h"
//生成测试数据的数组
TArray<FMyBackpackItem> FMyBackpackItem::MakeTestDataArr()
{
TArray<FMyBackpackItem> Arr;
Arr.Add(FMyBackpackItem("1"));
Arr.Add(FMyBackpackItem("2"));
Arr.Add(FMyBackpackItem("3"));
Arr.Add(FMyBackpackItem("4"));
Arr.Add(FMyBackpackItem("5"));
Arr.Add(FMyBackpackItem("6"));
return Arr;
}
//初始化物品data结构体
FMyBackpackData FMyBackpackData::FromItem(const FMyBackpackItem& Item)
{
FMyBackpackData Data;
Data.ItemData = Item;
Data.ItemNum = Item.InitCount;
return Data;
}
UMyBackpackComponent::UMyBackpackComponent()
{
PrimaryComponentTick.bCanEverTick = false;
}
//初始化背包数据
void UMyBackpackComponent::InitBackpackData(TArray<FMyBackpackItem> NewItemDataArr)
{
UE_LOG(LogTemp, Log, TEXT("UMyBackpackComponent::InitBackpackData,%d"),NewItemDataArr.Num());
for (const auto ItemData : NewItemDataArr)
{
if (ItemData.InitCount > 0)
{
const auto Item = FMyBackpackData::FromItem(ItemData);
UE_LOG(LogTemp,Log,TEXT("添加物品..........>>>"));
Backpack.Items.Add(Item);
OnItemAdded.Broadcast(Item);
}
}
}
//添加测试函数
void UMyBackpackComponent::AddTestData()
{
const auto TestDataArr = FMyBackpackItem::MakeTestDataArr();
InitBackpackData(TestDataArr);
UE_LOG(LogTemp,Log,TEXT("添加测试数据"));
}
//添加物品
void UMyBackpackComponent::AddItem(const FMyBackpackItem NewItem)
{
UE_LOG(LogTemp,Log,TEXT("进来了...添加物品"));
//先查找是否有项目,如果有,在原有基础上添加数量
for (auto Item : Backpack.Items)
{
if (Item.ItemData.Id == NewItem.Id)
{
UE_LOG(LogTemp,Log,TEXT("找到了项目,添加数量"));
Item.ItemNum += Item.ItemNum + NewItem.InitCount;
//调用绑定事件,添加物品到背包时调用
OnItemAdded.Broadcast(Item);
return;
}
}
const auto NewCreateItem = FMyBackpackData::FromItem(NewItem);
Backpack.Items.Add(NewCreateItem);
OnItemAdded.Broadcast(NewCreateItem);
UE_LOG(LogTemp, Log, TEXT("没找到,直接把物品添加到背包"));
}
//移除物品
void UMyBackpackComponent::RemoveItem(FMyBackpackItem Item)
{
const auto Find_Index = Backpack.Items.IndexOfByPredicate([Item](const FMyBackpackData& Ele)
{
return Ele.ItemData.Id == Item.Id;
});
if (Find_Index != INDEX_NONE)
{
const auto FindItem = Backpack.Items[Find_Index];
OnItemRemoved.Broadcast(FindItem);
Backpack.Items.RemoveAt(Find_Index);
}
else
{
UE_LOG(LogTemp, Error, TEXT("背包项目没有找到"));
}
}
//通过物品ID来移除某个物品
void UMyBackpackComponent::RemoveItemByName(FName ItemId)
{
const int32 Index = Backpack.Items.IndexOfByPredicate([ItemId](const FMyBackpackData& Ele)
{
return Ele.ItemData.Id == ItemId;
});
if(Index!=INDEX_NONE)
{
UE_LOG(LogTemp,Log,TEXT("通过ID来删除物品"));
const auto FindItem = Backpack.Items[Index];
OnItemRemoved.Broadcast(FindItem);
Backpack.Items.RemoveAt(Index);
}
}
//重置背包
void UMyBackpackComponent::CleanBackpack()
{
const TArray<FMyBackpackData> Items;
Backpack.Items = Items;
OnCleanBackpack.Broadcast();
UE_LOG(LogTemp, Log, TEXT("重置了背包数据"));
}
void UMyBackpackComponent::BeginPlay()
{
Super::BeginPlay();
//AddTestData();//添加测试数据
}
//获取背包
FMyBackpack UMyBackpackComponent::GetBackpack()
{
return Backpack;
}
void UMyBackpackComponent::TickComponent(const float DeltaTime, const ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}