• 9
• 10
• 9
• 11
• 14

# Polymorphism with C++/Lua

## Recommended Posts

So I'm trying to design an ECS system and I want to use Lua as my scripting language since it's regarded as very powerful and its widely adopted so its easier to maintain. Right now I want my component interface to be exposed to Lua and expandable. What I mean is, having the very simple following code:

struct Component {
virtual ~Component();
};


How can I make it so that a Lua script can create child components uppon that struct?

Thank you.

##### Share on other sites

Lua doesn't have classes natively, so what you must do is get a class implementation (or write one), and make a wrapper Lua class around your C++ code. Then in Lua classes, you derive from the wrapper class.

I don't think this counts as polymorphism, which in my view, is having a set of functions where the function to apply is selected on the type of the arguments. As far as I know, Lua doesn't have this concept at all, you can't even state a function signature, let alone you have several functions with the same name in a table with such type signatures. Likely you can write a polymorphic dispatch system in Lua if you really want, but as far as I can see, that would start with adding a type system first, so you can express a function signature.

##### Share on other sites
Make a derived class on the C++ side which implements every virtual function by calling a Lua function that it has stored as a member variable somehow. Bind that class to Lua. Lua sub-classes then create this C++ LuaComponent/etc object and plug their own functions / table of functions into it.

That said, don't make an abstract Component base class, and don't use polymorphism for components. Polymorphism makes sense when one algorithm can operate on multiple types of objects without caring what they are. Game "components" don't fit into that category.
With your current interface, the only algorithm you can write anyway is:
For each component, delete yourself.
..which is not something you need.

##### Share on other sites

I'm now leaning more and more towards the logical conclusion of components being 100% data with zero functions.

struct PositionComponent
{
float x, y;
};

Then a PositionSystem can do all the work on them.

Then an entity is pure data also:

struct Entity
{
std::string name; // make this a hashed value for integer comparisons
std::bitset<NumberOfComponents> componentList;
bool is_alive = true; // when killed off, set to false then the following frame actually destroy it.
};



Then if you want to get an entities component you can just pass the entity name into the system and get the data back.

The t-machine.org site has some good entity-component system articles, though more recent ones are in unity + c# :(

http://t-machine.org/index.php/2015/06/09/entity-ids-how-big-using-uuids-or-not-why-etc/

http://t-machine.org/index.php/2014/03/08/data-structures-for-entity-systems-contiguous-memory/

##### Share on other sites

@Hodgman or @Alberth , could you give an example of how you would implement such a thing, I'm very new to Lua so I'm not sure how I could do that.

@Mike2343 , yeah, but my component system is a map as such:

std::unordered_map<std::type_index, std::shared_ptr<Component>>;


And I want the component types to be expandable through Lua

##### Share on other sites

I'm now leaning more and more towards the logical conclusion of components being 100% data with zero functions.

Why do you think that is logical? That means that each component is pseudo-global data that any number of systems could operate on, which makes it hard to reason about and track down bugs.

Admittedly this isn't necessarily any better than an UberGameObject with everything inside it. But it is worse (in this regard) than having encapsulated components which have their own methods.

The T-Machine blog makes the error of disappearing down the 'objects in contiguous memory' rabbit hole; it's useful to work with contiguous memory if you can, but for the vast majority of cases I'd argue that you either want to go more object-based, and gain a ton of encapsulation, abstraction, and ease of use, or go the other way and attempt vectorisation or Struct Of Arrays on your high-performance data. Choosing the middle ground for everything doesn't seem to me like a good place to be.

##### Share on other sites
@Hodgman or @Alberth , could you give an example of how you would implement such a thing, I'm very new to Lua so I'm not sure how I could do that.

Guess three times what happens if you search for "Lua C++" in \$random search engine.

https://www.gamedev.net/resources/_/technical/game-programming/the-lua-tutorial-r2999

seems a first step, although 5.1 is old.

Edited by Alberth

##### Share on other sites

@Hodgman or @Alberth , could you give an example of how you would implement such a thing, I'm very new to Lua so I'm not sure how I could do that.

@Mike2343 , yeah, but my component system is a map as such:

std::unordered_map<std::type_index, std::shared_ptr<Component>>;


And I want the component types to be expandable through Lua

Have fun with that.  Mine are supported in Lua.  You should have no real use cases to add features to a component at run time either, they're so low level to begin with.