[Tutorial] Basic Inventory/Item System

After finally getting my own inventory system working id figure it would be a good idea to lend back the hand to the community so, Lets begin!

First we need an actor that will serve as our item

Item Header




UCLASS()
class AProojectItem : public AActor
{
	GENERATED_UCLASS_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Item)
	FString ItemName;



	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Item)
	int32 Value;

	UFUNCTION(BlueprintImplementableEvent, meta = (FriendlyName = "Item: Used"))
		virtual void Used();

	UFUNCTION(BlueprintImplementableEvent, meta = (FriendlyName = "Item: Dropped"))
		virtual void Dropped();


	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Item)
		TSubobjectPtr<class UStaticMeshComponent> Mesh;

	virtual void BeginPlay() OVERRIDE;
	void PickedUp();	
};


I used BlueprintImplementableEvent in the Used & Dropped functions so i could override these from a blueprint, since my items are blueprints i dont need to create a function in c++ for each one i just declare it on its blueprint

Item.cpp



AProojectItem::AProojectItem(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	Mesh = PCIP.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("Mesh"));
	RootComponent = Mesh;
}

void AProojectItem::BeginPlay()
{
	Super::BeginPlay();
	Mesh->SetSimulatePhysics(true);
	Mesh->WakeRigidBody();

}

void AProojectItem::PickedUp()
{
	if (Mesh)
	{
		Mesh->DestroyComponent(); // physical item has been picked up, destroy its visible component
	}
}


Now that we have our item actor we need an array to store these into

Character Header



UCLASS(config=Game)
class AProojectCharacter : public ACharacter
{
UPROPERTY(EditAnywhere, Category = Inventory)
		TArray<class AProojectItem*> ItemInventory; // Our Inventory

	virtual void Tick(float DeltaSeconds) OVERRIDE;
        void PickUpItem(AProojectItem* Item);
};



Now that we have the array the only thing we need to do is a get a pointer to the spawned item and add it to the array , for this i just do a trace each tick and check if its an Item class



#include "ProojectItem.h"

void AProojectCharacter::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	FVector CamLoc;
	FRotator CamRot;

	Controller->GetPlayerViewPoint(CamLoc, CamRot); // Get the camera position and rotation
	const FVector StartTrace = CamLoc; // trace start is the camera location
	const FVector Direction = CamRot.Vector();
	const FVector EndTrace = StartTrace + Direction * 200; 

	// Perform trace to retrieve hit info
	FCollisionQueryParams TraceParams(FName(TEXT("WeaponTrace")), true, this);
	TraceParams.bTraceAsyncScene = true;
	TraceParams.bReturnPhysicalMaterial = true;

	FHitResult Hit(ForceInit);
	if (GetWorld()->LineTraceSingle(Hit, StartTrace, EndTrace, ECC_WorldStatic, TraceParams))
	{
		AProojectItem* NewItem = Cast<AProojectItem>(Hit.GetActor()); // typecast to the item class to the hit actor
		if (bDrawDebugViewTrace)
		{
	      DrawDebugLine(
			GetWorld(),
			StartTrace,
			EndTrace,
			FColor(255, 0, 0),
			false,
			3,
			0,
			1
			);
		}
	

		if (NewItem) // if we hit an item with the trace
		{
			this->PickUpItem(NewItem); // pick it up
		}
	}
	
}



void AProojectCharacter::PickUpItem(AProojectItem* Item)
{
	if (Item)
	{
		ItemInventory.Add(Item); // add it to the array
		Item->PickedUp(); // hide mesh 
	}
}


By the end you should have someting like this

Remember to call the Used & Dropped events somewhere in c++ so they can be used in the blueprint!

Hope someone finds this useful :slight_smile:

WOW! Thanks we could use this and make some needed modification for our game. Very much appreciated.

thank u very much alvarofer0020 this is a great improvement :eek:

I’ve made a wiki tutorial of this page, which has a couple of changes in it including a node setup that lets you print the players inv so you can test if the items are being picked up:

I finally got working a easier way to give items to the player now you only need to get a reference to your player and give him the item with its name i.e GiveItem(“SodaCan”)

so First we need a database to keep a track of all the items the player can acquire im using a struct with a FString to identify the item and a subclass of our item
so it can be spawned & added to the inventory

Database Header


USTRUCT()
struct FItemData
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditDefaultsOnly, Category = Item)
	FString ItemName;

	UPROPERTY(EditDefaultsOnly, Category = Item)
		TSubclassOf<class AProojectItem> Item;
};
/**
 * 
 */
UCLASS()
class ADatabase : public AActor
{
	GENERATED_UCLASS_BODY()

	UPROPERTY(EditDefaultsOnly, Category = Database)
	TArray<FItemData> ItemClasses;

	TSubclassOf<class AProojectItem> GetItem(FString ItemName);
	
	
};


Database .cpp




#include "Prooject.h"
#include "Database.h"


ADatabase::ADatabase(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{

}


TSubclassOf<class AProojectItem> ADatabase::GetItem(FString ItemName)
{
	for (int i = 0; i <= ItemClasses.Num(); i++) // loop trough the whole DB
	{
	
		if (ItemName == ItemClasses*.ItemName) // if the item exists in our DB, return it
		{
			return ItemClasses*.Item;
			break;

		}
	}

	return NULL; // else dont return anything

}


Now that we have our Database FIRST we need to create a Blueprint of our new database class so we can load it from our gamemode , so later we can access it trough our player character

Gamemode Header



#include "Database.h"
#include "ProojectGameMode.generated.h"


UCLASS(minimalapi)
class AProojectGameMode : public AGameMode
{
	GENERATED_UCLASS_BODY()
	TSubclassOf<class ADatabase> GameDBClass; // our DB

	class ADatabase* GameDB;


};

Gamemode CPP


#include "Prooject.h"
#include "Database.h"
#include "ProojectGameMode.h"

AProojectGameMode::AProojectGameMode(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	static ConstructorHelpers::FObjectFinder<UClass> GameDBBPClass(TEXT("Class'/Game/Blueprints/Items/BP_DB.BP_DB_C'")); // change this to YOUR BP Path
	if (GameDBBPClass.Object != NULL)
	{
         GameDBClass = GameDBBPClass.Object; // assign our class
	 GameDB = GameDBClass->GetDefaultObject<ADatabase>(); // create it
	}

}


Now that the DB is properly intialized we can cast to our gamemode and then our DB to get the item

Character header


UFUNCTION()
void GiveItem(FString ItemName);

Character CPP


void AProojectCharacter::GiveItem(FString ItemName)
{
		AProojectGameMode* MyGamemode = Cast<AProojectGameMode>(GetWorld()->GetAuthGameMode()); // get our gamemode
		TSubclassOf<class AProojectItem> ItemToGive = MyGamemode->GameDB->GetItem(ItemName); // Call the DB GetItem function
		if (ItemToGive) // if we got a item / its not NULL
		{
			FActorSpawnParameters SpawnInfo;
			SpawnInfo.bNoCollisionFail = true;
			AProojectItem* NewItem = GetWorld()->SpawnActor<AProojectItem>(ItemToGive, SpawnInfo); // spawn it in the world so we can pick it
			ItemInventory.Add(NewItem);
			NewItem->PickedUp(); // Its been added to our inventory, we can hide its physical side now
		}
	    
}

Before using GiveItem remember to add all your items to your Database Blueprint so the array is valid

By the end of the tutorial you should have someting similar to this

Thank you very much it’s really helpful ! I have been working on my own Inventory and I was stuck on the 3DMesh part.

When it all works well I will share, it might interest some people.

#include “Prooject.h”
#include “Database.h”
#include “ProojectGameMode.h”

Prooject.h, what is this, please?
Thank you

These should be changed to your gamemode and UProject i.e MyProject, MyProjectGamemode

Im actually going to give the whole thing a big overhaul as well with the use of DataTables

Thank you very much…really hepful.

Excuse me again :slight_smile: I have seen you have got three Blueprints: BP_DB, BP_Item, and TestItemStructure, could you be so kind to explain relations beetween those BPs and your diferent class? Database class is the parent class for BP_DB? How to pass de BP_Item to BP_DB? Thank you for your consideration.
Other Question about this thread: A new, community-hosted Unreal Engine Wiki - Announcements and Releases - Unreal Engine Forums

TArray<class ABasicItem*> AProojectCharacter::GetCurrentInventory()
{
return ItemInventory;
}

TArray<class ABasicItem*> ?? You definition is TArray<class AProojectItem*> GetCurrentInventory();

Then, i have to change for this code??

TArray<class AProojectItem*> AProojectCharacter::GetCurrentInventory()
{
return ItemInventory;
}