Ask any game programmer, and they’ll tell you that it’s best to adopt a data-driven approach that allows game designers to tweak as much about the gameplay as possible without the aid of a programmer. If you talk to the game designers themselves, many of them will tell you that for games that require a lot of tweaking and balancing, it’s best to be able to manipulate this data directly with the very capable set of tools provided in Excel (or other spreadsheet tools).
So how can you get data defined by game designers out of Excel and into a format you can use in UE4? Well, I have some good news for you! This already works in UE4!
Unreal Engine 4 supports importing data from comma separated variable (.csv) files, which is a format to which you can easily export your Excel files. You can even make macros in your excel documents to allow you to export to .csv with the click of a button inside the document itself. There’s an example of a document set up in this fashion here:
- Example.xlsm (right-click and Save as... to download)
*Note that you may have to press the “enable content” button to allow the macros to run. This is a security feature of Excel to keep arbitrary code from running on your machine without your permission.
Types of Tables of Data
We find the following two types of tables of data to be useful:
- DataTables
- CurveTables
DataTables give you the freedom to define pretty much any type of data you want for import, whereas CurveTables are customized more for interpolating along a curve defined via floating point numbers.
Data Tables
With data tables you can define custom data structures and edit and maintain their values in Excel. You can define the format of the data by creating a struct that inherits from FTableRowBase, and defines various properties and default values.
As an example, here is a definition for level up experience data and the CSV document that supplies the data to the game:
/** Structure that defines a level up table entry */
USTRUCT(BlueprintType)
struct FLevelUpData : public FTableRowBase
{
GENERATED_USTRUCT_BODY()
public:
FLevelUpData()
: XPtoLvl(0)
, AdditionalHP (0)
{}
/** XP to get to the given level from the previous level */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=LevelUp)
int32 XPtoLvl;
/** Extra HitPoints gained at this level */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=LevelUp)
int32 AdditionalHP;
/** Icon to use for Achivement */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=LevelUp)
TAssetPtr<UTexture> AchievementIcon;
};
The corresponding CSV Document would look like this, where the first column is a unique name to identify the row of data. Later when retrieving the data, you refer to the row of data you want by name.
Name,XPtoLvl,AdditionalHP,AchievementIcon
1,0,0,"Texture2d'/Game/Textures/AchievementIcon1'"
2,1000,9,"Texture2d'/Game/Textures/AchievementIcon2'"
3,1000,10," Texture2D'/Game/Textures/AchievementIcon3'"
4,1500,12," Texture2D'/Game/Textures/AchievementIcon4'"
5,2000,14," Texture2D'/Game/Textures/AchievementIcon5'"
Curve Tables
Curve tables are a little more specific in their use, as floats are the only data they contain. You can use various formulas and tools inside of excel to define curves for XP or some other aspect of your game, and then evaluate these curves in UE4.
For example, you could define curves for how damage increases based on character level or some other factor like so:
Example
Here is an example table for damage progression curves (as you can see the column numbering need not be sequential integers, so you can include gaps):
0 |
2 |
3 |
7 |
|
---|---|---|---|---|
Melee_Damage |
15 |
20 |
25 |
30 |
Melee_KnockBack |
1 |
2 |
4 |
8 |
Melee_KnockBackAngle |
10 |
45 |
60 |
65 |
Melee_StunTime |
0 |
1 |
5 |
7 |
Curves are particularly useful for balancing, item distribution, attributes for abilities and skills, etc. You can also evaluate any point on the curve you defined. For example if you had a monster whose health varied depending on the difficulty setting of the game, you could define a health curve that ranged from 100 to 10,000 in a linear, cubic, or some other fashion. Then you could sample the curve at say 75% of the way from minimum to maximum value to find the amount of health for “Hard” difficulty.
Importing
The importing process is pretty easy. You just export your Excel (or whatever software) spreadsheet to .csv format, and you can drag and drop that onto the Content Browser.
Currently, if you have the .csv file open in Excel when you try to import it into UE4, it fails without a very clear error message, so remember to close the file in Excel before you import. We’re looking into this issue.
You’ll be presented with a dialog to choose whether this is a DataTable (and thus also the Row Type defined earlier in C++) or CurveTable, in which case you have to choose a type of interpolation between the curve points, i.e. Linear or Cubic, etc:
From there you’ll see a Data Table or Curve Table asset in the Content Browser, and you can double click it and open it to inspect the values.
Using the Data
In order to make the Data as easy to set as possible, I recommend making a Blueprint-exposed variable of Type FDataTableRowHandle or FCurveTableRowHandle. Then in a Blueprint a designer would specify the Table and the Row Name.
Once these references are set, you can call FCurveTableRowHandle::GetCurve() to get a FRichCurve, or FDataTableRowHandle::FindRow() to get a reference to an instance of the struct you defined earlier. You shouldn’t hold on to these references any longer than the scope of a function though, because if the data is re-imported, you want the changes to take effect instantly, and you don’t want to access any invalid pointers.
Further Information about DataTables and CurveTables
See the Data Driven Gameplay Elements documentation.
I hope this post helps you use Excel to improve your design process, but as always feel free to post further questions on AnswerHub or in the Forums!