I am working on an item system that includes things like weapons, equipment, consumables, etc. I am currently using a pickup class system in which each item has an item version and a pickup version. The pickup version has very little data on it but spawns the heavier item class version when interacted with. I like this system since it means I make one hard reference to the item class (which is pretty light) and then can theoretically add as many items as I want to the game without increasing the number of hard referenced assets to my player character.
I have read that some consider a data table as a better way to do large scale projects, however, this seems somewhat counterintuitive to me as, even if I were to use soft references for a lot of assets, wouldnât I still need to have a very large amount of data (which would increase proportionally the amount of total items in my game) loaded at any given time? Obviously, a data table is very convenient for item stats since you can manage all of them in one place, but scalability wise (in terms of maximizing total content without limiting performance) would I be wrong to think that a data table creates a lot of hard reference related limitations?
Why would data tables generate more data than an actor-class-per-object-type? You still need all the same data â inventory icon, in-world mesh, trigger script, etc.
I would go with a data table or data assets, and then have a generic âin world pick-upâ actor class, and a generic âin inventoryâ object, which can reference the data instance (struct or data asset) There can be an optional, soft-referenced actor class for what to do if the user tries to âactivateâ or âwieldâ or âwearâ the thing in question.
Even that could be shared â every âpistolâ is the same actor class, and only the data items (mesh, rate, sound effects, ammo, âŚ) would change as configuration data.
Basically, too many specialized actor classes will become quite unwieldy when they get into the thousands. Itâs still a little bit grayscale, because if you use blueprints to configure many âpistolâ instances, technically each of those are still a new actor class, so youâre going to have to figure out exactly how far you want and need to take it.
Its possible that I donât fully understand the concept here, but my understanding was that if I have an item class, my player blueprint only needs to know what variable types are associated with that item class, and, assuming I only have one item equip at a time, then I would only need to store the information for that singular pickup (i.e. its damage, range, model, etc). If I use a data table, it would seem to me that I would need these data entries (damage, range, model, etc) for every item of that class all at once, despite only needing the actual information for a single item. Is this not true? In other words, I donât think data tables generate more data overall, but rather they would seem (from my understanding) to need to access more data at any given instance.
My current system basically just has a parent class that is âwieldable itemsâ (which has no variables and is just used to group the subclasses so that I can store items of different child classes in the same inventory array), and then a child class for guns, equipment, etc.. All guns are then child of the guns class, equipment of the equipment class, etc.
accessing a DataTable does load all data within it, for things like damage/range this is nothing
for assets like materials/sounds you should use soft assets and especially for classes they must be soft class references or you will load every item in the game, unless thats what you want.
DataAssets are much better but also slightly more complicated if youre new.
I personally would never use a DataTable for Items as they are restricted by a single struct, so if you have weapons,armor,items they all need to share the same struct which leads to weapons with armor values etc
Oh I see, so is it less about the fact that a lot of data is loaded and more about the fact that certain values are very cheap? I am still fairly new to these concepts and am not familiar with data assets yet, but I will certainly take a look at the concept. So even if I had ~100 items, each with ~20 floats, 10 enumerations, and 5 or so soft referenced meshes, sounds, etc (maybe more variables in the future), this would be negligible to have loaded at all times? What if I had ~1000 items, would this still be practical? Lastly, how would I go about having custom logic associated with individual items? I currently have the general item logic in my player blueprint which is selected based on enumerations in the specific items. For very unique items, I may need to put some logic in the individual items blueprints, would this still be possible?
All of this being said, I donât currently plan on having more than ~100 items, realistically probably less than 70. Im more interested in learning good practices that would make it possible to scale this further if needed but I certainly wouldnât expect more than 300 ever.
Assuming I keep the associated blueprints organized, is a pickup/item system like what I have described inherently bad (I.e. having lots of actor blueprints), or is it more a matter of organizational convenience that comes with data assets?
if its just data this is nothing so donât worry.
simple way, if your items are classes you can use an interface
advanced version, each âactionâ is a class of its own, similar to GAS
this is bad practice, but maybe fine for a small game, players and items are separate things and should not be mixed.
its not bad, it just depends on your game.
The most important thing, always, is to get your game down. the pit of âis there a better wayâ is never ending and will only slow you down. but its good to learn for future.
Ok I think that makes sense. With reference to the weapon logic being stored in the weapon itself, the reason I initially chose to have it in the player blueprint was to avoid redundancy since all weapons use roughly the same base code and I felt like that didnât need to be present (by way of inheritance) in every single gun blueprint, however, it seems like this really doesnât need to be a concern based on the data table discussion.
Also, I have done some reading into this subject and I think I would benefit from moving to data tables. It sounds to me like data assets might be challenging for me to work with since it seems they are less blueprint compatible from what I am reading. I have, however, heard some issues with structs and enumerations in data tables (causing crashes/data loss). Are you familiar with these being problematic or is this something that may have been fixed?
nope its still a big issue, its caused by changes to the struct/Enum (BP only, C++ seems fine) so if you do that i recommend simple small structs not monolithic or nested ones and if you change anything include renaming it or fields backup everything
The most important questions you need to answer in this case is:
Do your items need balancing and in what form will that balancing come.
Most often balance is done in tables so there is nothing easier then exporting a .csv and using it as a Data Table. Creating Data Assets and modifying them by editor scripts fed by tables is not impossible too but it is a hassle.
That being said, it is almost unavoidable to have assets in your game and they usually contain some data They are not necessary Data Assets but they can hold variables which are item specific and can reference their row in the DataTable.
In conclusion:
You canât go wrong with Data Tables if you keep them simple and small. Donât put in it things you wonât change frequently. Use them for things that have to be edited in bulk according to a formula or that will be frequently changed in number. It is much easier to add 100 table rows than to create 100 data assets.
I donât often find the use for Data Assets because my items are handled either as Actors, UserWidgets, structs or units (ID) within my systems.
This is my personal experience though. I realize that I might be in the minority.
I greatly appreciate everyone who has provided info on this so far, it has been really helpful!
Again, since Iâm pretty new to this let me recap what I am thinking based on what I have learned. I have a lot of weapons and items in my game in several different classes (Guns, melee weapons, throwable items, equipment items, and consumable items), currently each with a child pickup class and child item class. Assuming I want to use data tables I wouldâŚ
Create a data table for each class which would contain all of the data that might be balanced or altered in the future (but is static during gameplay). These would include data like damage, range, ammo capacity, melee range as well as soft references to meshes, animation montages, sounds, etc (the specifics depending on that item class of course).
Create a single item class for each of the major categories (guns. melee, etc). These will all likely be hard referenced to my player blueprint and will have all of the code to make the items work (i.e. code to shoot, reload, etc) but will not contain anything heavier like skeletal meshes.
I will probably keep a unique pickup child class for each of the items as I like being able to see the meshes in the editor (as apposed to loading them on begin play) but each pickup will really only contain a mesh, and a text key to access the corresponding data table row.
When a pickup is interacted with, it will access the corresponding data table, get the mesh, stats, and sounds of the item which it is (based on the text key), and then set all of these values (that way they are no longer soft references and wont lag behind during gameplay) in the singular item blueprint of that class so that any code already associated with that class can function appropriately based on whatever data just got set.
My only remaining question is, assuming I want to have unique code such as a special attack on one of my weapons, would I simply have this be accessed via a specific entry in an enumeration for that specific weapon since I will no longer have a unique item blueprint for it?
I would keep the pickup as lightweight as possible. Instead of the pickup reading the data table itself, have it only pass an item ID or row handle to the inventory/equipment system and let that system load or apply the item data.
Imo also avoid having the items directly communicate with the character. the character or its inventory/equipment systems should be the ones interacting with and driving the items. That keeps the dependency chain cleaner.
The first point makes sense, but for the second once, could you elaborate on what you mean by avoid having items directly communicate to the character? Do you just mean I shouldnât have a hard reference between the master weapon blueprints and the player character (i.e. just try and use interfaces to replace these dependencies)? Or are you saying that I shouldnât have the item themselves do anything in the character blueprint and only have the character blueprint tell the items when to do things? Or both? As far as inventory goes, I have this in my character blueprint as well if that makes a difference.
This is mainly what I mean for communication: Character â item system â pickup.
The character owns the item system, and that system handles overlap/interact logic, validates the pickup, checks inventory space, equips it, or gives feedback if full. The pickup should stay lightweight and not need to know about the character directly.
It could also be a subsystem and dynamically bind while still working the same way. My main point is that the control flow should be system-driven rather than pickup-driven.