I’m a bit confused about the proper way to handle static data in a game. By “static data,” I mean data that doesn’t change throughout the lifetime of the game: the stats of various weapons, how much HP each enemy has, etc. DataTables seem like the right place to start, but I can’t figure out how to actually use data from a data table in game.
As an example, let’s say I was making a CCG with a set of static, built-in decks that players could use. In normal (non-Unreal) C++, my data structures might look something like this:
struct CardDefinition
{
const char* Name;
const Texture2D* Art;
// Some other members
};
static const CardDefinition] gAllCards =
{
{ Name = "FirstCard", Art = GetAsset("some/path") },
{ Name = "SecondCard, Art = GetAsset("some/other/path") },
// etc.
}
struct CardEntry
{
const CardDefinition* Card;
const int Quantity;
};
struct Deck
{
const CardEntry] Cards;
};
static const Deck] gAllDecks =
{
{
{ Card = gAllCards[0], Quantity = 2 },
{ Card = gAllCards[1], Quantity = 3 },
// etc.
}
}
// Then, somewhere in gameplay code...
class InGameDeck
{
//...
void Initialize(const DeckDefinition& deck);
const CardDefinition& DrawCard();
//...
}
One problem with this is that it is completely opaque to designers. This isn’t necessarily a huge issue in my case, but I’d like to learn the “correct” way of doing this, which means making as much of this as possible blueprint-accessible. I’ve tried a handful of different approaches, but haven’t found anything that entirely works yet:
I can create a Blueprint Struct for CardDefinition and then a DataTable of this type for AllCards. However, after doing so, I can’t find any way to create a Blueprint Struct for CardEntry that references a row in this table. It doesn’t look like FDataTableRowHandle is visible to blueprints.
If I define my structs in C++ and am willing to throw type safety to the wind, I can have CardEntry include a member of type FDataTableRowHandle. However, this makes any functionality involving this inaccessible from blueprints, as I can’t find a way in blueprints to go from a FDataTableRowHandle to the underlying CardDefinition. This means that I can’t call InGameDeck::Initialize() from a blueprint.
In addition, I can’t seem to find a way to have InGameDeck::DrawCard() return a const reference to a CardDefinition. The engine seems to think that const reference types should only be used on input pins, so I get an error complaining about direction. I could have it return a non-const pointer, but that makes me somewhat uncomfortable as the it’s referring to definitely should not be mutated at run time. I suppose I could make both Initialize() and DrawCard() deal with FDataTableRowHandles instead of CardDefinitions, but once again, I’m throwing away type safety if I do that. I’d really prefer to read the data out of the tables once at game start and then pass around references to the underlying types everywhere else.
This all makes me think I’m going about static data the wrong way. Can anybody point me at a way to handle static data that allows me to define and manipulate data from blueprints in a type-safe, const-correct manner? Is there an example project I could look at that demonstrates a good way to manage this?