Dev Blog 3 - We're late!!!

Hi, everybody! It’s me, Bites. I just bought Katamari Damacy Rerolled the other day, and I had a blast playing through it, but… before I knew it, it was over. I want more!

Maybe we can have a Katamari-esque party game in Rolled Out…? Well, even if we don’t do anything like that, you could probably make something using Lua.

Anyways, did you notice? Did you see? We’re on a whole new website!

…sorry, come again? You said something like,
“Show us the update! Stop stalling!” and then started hitting me with a stick?

Well, I can’t argue with that kind of excitement. Let’s get into it.

What we have this week isn’t very visually interesting, apart from a bit of concept art by Laurence.

Train Concept

What in the world could this possibly be for, you may be asking…?!

It’s just the train background. Sorry, nothing very special. Moving on!

Here’s a little taste of magic for you - it’s music!! These tracks aren’t necessarily final, nor may they even make it into the full game release… but we wanted to grant you a glimpse into the kind of tunes you may be hearing in the game.

These tracks were produced by two of our newer members to the team, Baycun and Chimeratio.
Go check them out!

Chimeratio’s
Bandcamp,
Soundcloud,
Twitter

Baycun’s Bandcamp,
Soundcloud,
Twitter


That’s the straightforward stuff. CraftedCart has prepared another fairly in-depth report on what they’ve been tackling codewise.

If you like technical details, soldier onward. I recommend you read it, even if you don’t understand it!


Types about types

I don’t have a whole lot to report on in terms of interesting or otherwise noteworthy changes to Rolled Out! this fortnight, so I hope you don’t mind if I delve into C++ talk here, mostly involving some template magic (or at least what I consider template magic).

Templates? What are templates?

For those of you unfamiliar with C++, templates are, well, templates. They allow a programmer to define a template for some code that, when compiled, can be duplicated with the blanks filled in by the compiler as needed.

Let’s take a small example of where templates may be helpful, a badly written resizable array.

1
2
3
4
5
6
7
8
9
class AnArray {
private:
??? *data; // The memory address of where the element list is
size_t size = 0; // How many elements the array has

public:
void append(const ???& value);
const ???& get(size_t index);
};

C++ requires that we define the type of everything. There are good reasons for this - one example in this case is that the compiler needs to know how big each type is when compiling. If I want to make an array of integers, the compiler needs to know that four bytes of memory need to be allocated for each integer in the array; if I want to make an array of ASCII characters, only one byte needs to allocated for each item.

Array memory map

We could just define the data types we want to store right in the class, but this presents a bit of a problem: what if we want two arrays, each storing different types of data?

Well, we could duplicate the class, each time swapping out the data type stored.

1
2
3
4
5
6
7
8
9
10
11
12
class AnIntArray {
private:
int *data; // We replaced `???` above with `int`
size_t size = 0;

// ...
};

class AFloatArray { /* ... */ };
class AStringArray { /* ... */ };
class AByteArray { /* ... */ };
// etc.

As you may imagine, this gets quite convoluted, and quite a big pain to maintain (If I want to modify the behaviour of this array, I need to edit a whole heap of duplicated code). What if we could ask the compiler to just duplicate the code for us?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template<typename T>
class AnArray {
private:
T *data;
size_t size = 0;

public:
void append(const T& value);
const T& get(size_t index);
};

// And I can use the array like such
AnArray<int> intArray;
intArray.append(42);
intArray.append(-27);
intArray.append(1204307);
intArray.append(2077);

AnArray<char> charArray;
charArray.append('R');
charArray.append('o');
charArray.append('l');
charArray.append('l');
charArray.append('e');
charArray.append('d');

Now we have a templated array with a placeholder of T, for type. Above we ask for integer and character arrays, which cause the compiler to generate code for AnArray twice, once for working on integers, and again for working on characters.

Custom RTTI

Run-time type information, otherwise known as RTTI, is a feature of many programming languages that allows a program to fetch information about the types of objects while the program is running (as opposed to while the program is being compiled). This can be quite useful in places.

For example, each stage contains a hierarchy of components. Every component is a SceneNode, however there are specialized (derived) variants of the SceneNode type used in various places, such as the GoalNode for a goal or the MeshNode for a 3D model. If I’m given an object and all I know is that it’s a SceneNode, how can I tell whether it’s a plain ‘ol SceneNode, or whether it’s one of the specialized varieties such as GoalNode?

Well there are a few different ways I could resolve this.

Option 1

I could have just added some “get” function in the each class that returns an enumeration with the type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
enum class EnumNodeType {
SCENE_NODE,
GOAL_NODE,
MESH_NODE,
};

class SceneNode {
public:
virtual EnumNodeType getType() {
return EnumNodeType::SCENE_NODE;
}
};

class GoalNode : public SceneNode {
public:
virtual EnumNodeType getType() override {
return EnumNodeType::GOAL_NODE;
}
};

class MeshNode : public SceneNode {
public:
virtual EnumNodeType getType() override {
return EnumNodeType::MESH_NODE;
}
};

This would work fairly well for our use case - each node gets its own entry in EnumNodeType, and calling getType() on a node would reveal it’s specialization. Where this breaks down is if you want to use this method across modules (specifically if modules want to create their own types derived from SceneNode) - it is very much impossible for outside code to add its own types to EnumNodetype and therefore have getType() return its own values. This wouldn’t matter however for Rolled Out! as we won’t be needing nodes split across various modules.

Option 2

Option two would be to use the RTTI built in to Unreal Engine. Well, this was out of the question. Unreal only exposes type information for UObjects, and given that stage loading should be able to take place on a separate thread, UObjects were out of the question for being unsafe to use on anything other than the main game thread.

Option 3

Option three would be to enable C++’s built-in RTTI support. Unreal Engine disables the built in RTTI by default but it can easily be enabled with a single line to the build script.

1
bUseRTTI = true;

This would have worked and have taken be all of about ten seconds to enable… but I didn’t. Aren’t I bright?

Well hold on, I’ll explain my reasoning in…

Option 4

Option four, which is what I settled on, is to hand-roll my own RTTI system. So why did I decide to roll my own instead of just using the C++ built-in one?

…well to be honest I don’t have a very good reason yet beyond “it seemed like a good idea and I wanted to learn about some template voodoo magic anyway”. Also C++’s built-in dynamic_cast is known for being a bit on the slow side so if I can make my own more stripped-down version that might give us a bit of a performance boost… maybe. Really though the decision to roll my own system is just what seemed like a good idea at the time and I’m gonna stand by that.

…also I forgot typeid was a thing but whatever MOVING ON.

Type tags

Type tags are my equivalent to C++’s std::type_info objects. Only one type tag can exist for each type, and each type tag stores some metadata about each type.

As a starting point, here’s a basic type tag class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class FTypeTag
{
public:
const TCHAR* Name;
SIZE_T Size;

private:
FTypeTag(const TCHAR* InName, SIZE_T InSize) : Name(InName), Size(InSize) {}

public:
template<typename T>
static const FTypeTag* From()
{
static FTypeTag Tag = FTypeTag(FPMetaType<T>::GetName(), sizeof(T));
return &Tag;
}
};

Suddenly, the coding style’s changed! This is to match the Unreal style guide.

From() is a templated method here that takes the templated type, gets its name, gets its type, and creates a new type tag from it. This tag variable is marked as static so it will only ever be created once no matter how many times you call the function. It can be used as such.

1
FTypeTag* IntTag = FTypeTag::From<int32>();

You may think that Tag being static would be an issue if you want to fetch the type tags of two different types, however remember that this templated code will duplicated for each different type we choose to get a type tag from. Therefore only one instance of the tag variable will exist for each type. Nifty huh?

Next up: how do we get the name of each type, and why would I need it anyway? Well for the latter question, having the name of each type can be handy for some friendly error reporting (this could be useful when it comes to debugging Lua). As for the former, FPMetaType is a struct I have just for that.

1
2
3
4
5
6
7
8
template<typename T>
struct FPMetaType
{
static const TCHAR* GetName()
{
return TEXT("[UnregisteredType]");
}
};

This is a simple struct with one function: GetName(), and all it returns is… “[UnregisteredType]”? And why is the struct templated anyway if I don’t even have any placeholders to fill in?

Ah, well templates in C++ can have some specializations.

1
2
3
4
5
6
7
8
template<>
struct FPMetaType<int32>
{
static const TCHAR* GetName()
{
return TEXT("int32");
}
};

This is a specialization of the above FPMetaType struct for the int32 type. Template specializations allow me to provide custom functionality for certain types: in this case my custom functionality is changing the GetName() function to return “int32” instead of “[UnregisteredType]”. To make these specializations a bit more convenient to create, I can bundle it up all into a macro.

1
2
3
4
5
6
7
8
9
#define P_DEFINE_META_TYPE(T) \
template<> \
struct FPMetaType<T> \
{ \
static const TCHAR* GetName() \
{ \
return TEXT(#T); \
} \
};

Now all I need to do to create an FPMetaType specialization is…

1
P_DEFINE_META_TYPE(int32);

If we go back to our original type tag code now, the way we get a name now should hopefully make some more sense. Calling FPMetaType<T>::GetName() will try to call GetName() on a specialized FPMetaType if it can. If no specializations exist for the type T, it will fall back to the original non-specialized version and GetName() will return “[UnregisteredType]”.

Sweet - so now we can get type tags that we can store and pass around at runtime. Slight issue though: this only works if we know the types we want to fetch type tags for at compile time (read: does not work with polymorphic types). So how can we get the right type tags when given an instance of a polymorphic type?

Well first we need to be able to get a type tag from an instance of a type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template<typename T>
static const FTypeTag* From(T* Object)
{
return FTypeTag::From<typename TRemoveCV<T>::Type>();
}

template<typename T>
static const FTypeTag* From(T& Object)
{
return FTypeTag::From<typename TRemoveCV<T>::Type>();
}


// Use as such
SceneNode* Node = new GoalNode();
// The compiler will automatically infer the template parameter <SceneNode>
FTypeTag* GoalTag = FTypeTag::From(Node);

That was easy enough, although the above code will still just give us the SceneNode tag instead of a GoalNode tag.

So how do we handle getting the type tags for polymorphic types? Well we can add type tag information into the objects themselves (and now we’ve looped back round to a solution similar to option one, but without needing to maintain an enum). For each polymorphic type that I want to be able to get type tags for, I add a function GetTypeTag().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class FSceneNode
{
public:
virtual const FTypeTag* GetTypeTag() const { return FTypeTag::From<FSceneNode>(); }
};

P_DEFINE_META_TYPE(FSceneNode);

class FGoalNode
{
public:
virtual const FTypeTag* GetTypeTag() const override { return FTypeTag::From<FGoalNode>(); }
};

P_DEFINE_META_TYPE(FGoalNode);

Again, to make adding these functions easier, I can bundle it up into a macro.

1
2
3
4
5
6
7
8
9
10
11
#define P_ENABLE_META_TYPE() \
public: \
virtual const FTypeTag* GetTypeTag() const { return FTypeTag::FromInstance(*this); } \
private:

// And FTypeTag::FromInstance is defined as such
template<typename T>
static const FTypeTag* FromInstance(T& Object)
{
return FTypeTag::From<typename TRemoveCV<T>::Type>();
}

Now, if we’re given an object that’s polymorphic, we can call GetTypeTag() on them to figure out their specialization if they have any.

Finally, to make this all a bit more convenient I can use more template magic to determine if a type has a GetTypeTag() function. With this I can add more FTypeTag::From overloads that, if given a polymorphic object with a GetTypeTag() function, will call that instead of just using FTypeTag::From<typename TRemoveCV<T>::Type>(). I am not going to go into details into how that works given that this post is already more than long enough, but if you want to look it up, the term to search for is “SFINAE”. I’ll also throw my code up on GitLab for reference.

And now, after all of that, I can compare the types of objects and fetch some information about a type’s name and size at runtime.

…and before you ask, no I haven’t gotten my own dynamic_cast in yet.

And all of this for what?

Two reasons mainly:

  • Lua type safety
  • Checking what kind of components various bits of a stage are (goal vs mesh ms bumper vs etc.)

I’ve been focusing a lot on the latter point throughout this post, but what really started this long tangent was Lua. Initially I wanted to add some simple type tags such that if some Lua code wants to change up how the game works, the game can check that the script doesn’t try to set variables/call functions with the wrong types, and gets an appropriate type when reading data from the C++ side of things.

And hey, now that I have control over RTTI I can add whatever I want to it, including stuff that’s not in the C++ built-in one. I already use it to store more friendly type names for the aforementioned friendly error reporting (I’m sure you’d prefer an error message to say “Expected type int32” instead of “Expected type i”), as well as the size of types if I need to twiddle around with memory.

In short…

  • I forgot typeid was a thing in C++
  • I went off and made my own type tag objects in anticipation for safe Lua scripting
  • I wanted to be able to check the types of polymorphic objects some time later
  • I decided to just tack-on that functionality to the existing type tags
  • Now I have control over the RTTI instead of leaving it to the C++ standard

Credit where credit is due

Kudos to the posts at https://codereview.stackexchange.com/a/70112 and http://www.axelmenzel.de/articles/rtti for helping me wrap my head around type tags and RTTI.