跳到主内容
Documentation

1.创建背包组件.md

2025/12/16预计阅读 13 分钟

创建一个背包组件

继承ActorComponent组件 img.png

创建背包相关模型

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

返回顶部