Announcement

Collapse
No announcement yet.

[Tutorial] Basic Inventory/Item System

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    [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
    Code:
    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

    Code:
    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

    Code:
    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

    Code:
    #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
    Last edited by alvarofer0020; 04-22-2014, 03:06 PM.
    Offering my Freelance Game Design ,Counselling and C++ Programming Skills!
    https://forums.unrealengine.com/show...ner-Counseling

    Marketplace Assets
    Melee Tracing Plugin:https://forums.unrealengine.com/show...Tracing-Plugin
    Medieval Combat Starter Kit:https://forums.unrealengine.com/show...at-Starter-Kit
    Foliage To Blueprint:https://www.unrealengine.com/marketp...e-to-blueprint

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

    Comment


      #3
      thank u very much alvarofer0020 this is a great improvement

      Comment


        #4
        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:

        https://wiki.unrealengine.com/Basic_..._/_Item_system
        Unreal is to Unity as Google is to Bing

        Programming is the art of turning something logically complex into something thats simply logical

        Tutorials and helpful things of mine:
        Custom Blueprint Node Creation
        Code snippet: Blueprint Node - Create Object from Blueprint
        Code snippet: Blueprint Node - Math node

        Comment


          #5
          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

          Code:
          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

          Code:
          #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[i].ItemName) // if the item exists in our DB, return it
          		{
          			return ItemClasses[i].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

          Code:
          #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

          Code:
          #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

          Code:
          UFUNCTION()
          void GiveItem(FString ItemName);
          Character CPP

          Code:
          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

          Offering my Freelance Game Design ,Counselling and C++ Programming Skills!
          https://forums.unrealengine.com/show...ner-Counseling

          Marketplace Assets
          Melee Tracing Plugin:https://forums.unrealengine.com/show...Tracing-Plugin
          Medieval Combat Starter Kit:https://forums.unrealengine.com/show...at-Starter-Kit
          Foliage To Blueprint:https://www.unrealengine.com/marketp...e-to-blueprint

          Comment


            #6
            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.

            Comment


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

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

              Comment


                #8
                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
                Offering my Freelance Game Design ,Counselling and C++ Programming Skills!
                https://forums.unrealengine.com/show...ner-Counseling

                Marketplace Assets
                Melee Tracing Plugin:https://forums.unrealengine.com/show...Tracing-Plugin
                Medieval Combat Starter Kit:https://forums.unrealengine.com/show...at-Starter-Kit
                Foliage To Blueprint:https://www.unrealengine.com/marketp...e-to-blueprint

                Comment


                  #9
                  Thank you very much...really hepful.

                  Comment


                    #10
                    Excuse me again 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: https://wiki.unrealengine.com/Basic_..._/_Item_system

                    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;
                    }
                    Last edited by pc-jose; 05-29-2014, 05:17 PM.

                    Comment

                    Working...
                    X