Since i have a pretty fixed setup for a working inventory in my head, i need some infos about what you are doing here.
So you have an InventoryManager and you created these different variables that can hold an item per slot. Where is your actual inventory? Is it the “Bag”?
I guess it is. So you want to access an item that is inside this Bag Array? You can just take the Item you want to view out of your Bag Array and maybe cast to it the specifc item you are using. Now you should be able to get the attributes you made inside your ItemClass.
What are the members of your AWeapon class? If there is an FName Name attribute that is also a UPROPERTY(BlueprintReadOnly), you should be able to drag from your Primary Weapon node and get the Name attribute and cast it to a string before plugging it into Print String.
I would take a look at the TSubclassOf template again. What you are getting in you Blueprints is actually a UClass object if I am not mistaken. To access the properties, I would suggest spawning an instance of the object first. This is similar to how the examples spawn a projectile from a TSubclassOf object in the shooter examples. Long story short your Primary Weapon get is returning a UClass object, not an AWeapon object, hence no access to the properties.
I would recommened not to save the whole actor AS actor, although you could if it’s an item that is spawned to your character like the sword. I would rather save the item properties itself. You could make a struct for them and make an array of this struct for your character. You could define itemtypes with an enum also stored in the struct and check the enum if you want to know if its a sword/weapon. You can display the model of the weapon by just assigning it to a component you have created for you character etc…
That seems like a lot of overhead to save it as a struct. What if theyes want to spawn a particular weapon? Or if they have over 500 different items in the game? That’s too large for an enumerated list and it becomes unmanageable, imagine the switch statement. Plus they would them need to fetch mesh, collision, and other references for when they do spawn an item. It would be far better to save a pointer to the base item class in the array and when it is picked up, disable the collision and rendering of it. Another option would be an Item Factory that tales in these subclasses and spawns them in the world when needed, then you wouldn’t need multiple objects existing in the world for different inventories.
What? I never said that the enum should be the item. It only tells the type. Like armor, weapon, trinket etc. I don’t think you have 500 item types.
The struct contains every information about the item. So you just spawn the base class depending on the itemtype and fill the struct back in zo the spawned item. My inventory system is completely running so i know it works like this
I have to do this at the Inventory manager init, and for equiping item right ?
or I can do it with pointer, and use only equip() function where equip will be charged to spawn and attach the Item. My slot will bee TSubobjectPtr initialized by default a NULL and equip() will set it to the pointer of the equiped item what do you think ?
Yes, it’s data driven. (: And yes, you can handle this with a data row etc.
I didn’t know how his Inventory worked, so thought that he maybe got the idea wrong.
He can’t access the properties because he only gets the uclass, you are right there too. He needs to spawn the Actor to be able to access the properties.
As long as the item is spawned in the world, he can reference it with his pointers etc.
Ah, I see you what you are saying now. I was confused, my apologies. This is a more data-driven approach then? Because if that is the case you could create a data row handle from the struct and fill in properties from there… But this is all out of scope of the question. I think Talus just wanted to know why he could not access his properties from the TSubclassOf getter in BP and that is because it is returning a pointer to a UClass base object.
Personally, I have always gone the raw pointer route. The only caveat is that the item must exist in the world before assigning it. In which case, equip would not need to spawn the object.
Here is an awesome blog post about a UsableItem system that evolves into a robust inventory system, I highly suggest reading it as it comes with source code downloads (C++ and BP). I have used it for the basis of two inventory systems for some of my clients:
Wups, i wanted to convert your comment to an answer and keep your konversation with Talus in it. I guess i can’t do this Sorry for messing up the Comment order/structure >.<
EDIT: Wuhu, managed to merge the comments xD now he can accept your answer if you are finished helping him.
and my equip() will be a generic function for equiping Weapon or Armor (item directly see in world), I need to spawn it before assigning it
but this will work with class derived in BP, by example my test weapon W_test is a BP extended from AWeapon, W_test can assign into the pointer weaponSlot after spawn ? with cast ?
for the Bag slot, it’s a “garbage” inventory, just SubclassOf can be use here and if the player equip from the bag I can spawn the correct object using the subclass.
Pointers in C++ can point to inherited class objects without issue. The only thing is, if you need to access a child class’s function (W_test) you will then need to cast to W_test. For instance:
AWeapon* MyWeapon = new AChildWeapon(); //Where AChildWeapon : public AWeapon
Would be totally valid in raw, vanilla C++. Of course, you wouldn’t want to use new (for the most part) in UE4 engine (as objects won’t be created properly).
But yes, that is the general idea. Again look at the blog posts from tomlooman.com as it is very helpful in doing what you are trying to do.