7
\$\begingroup\$

My engine uses a component-based entity system internally, and I want to bind it to Lua for scripting.

Now, I want to save people who write scripts for it typing work. In C++, to set the position of an entity, you'd do the following:

pEntity->GetComponent< CPoint >()->SetPos( Vector( X, Y ) );

That means, if I'd bind it to Lua 1:1 you'd also have to:

ent:GetComponent( CP_POINT ):SetPos( 123, 456 )

But let's be honest, would you want to type so much just to set an entities' position?

I don't think so, that's why I "hid" the component system from Lua:

Right now, what you do is

ent:SetPos( 123, 456 )

The component stuff is handled internally. You can still manually add and remove components from Lua with ent:AddComponent and ent:RemoveComponent, etc.

Now, this doesn't seem perfect either:

  • The Entity metatable gets cluttered because it has to take all functions of all components

  • Naming problems: ent:SetJointMotorEnabled() again seems kind of bad

Do you have any ideas how I could find a better naming scheme for component functions, without risking the scripting comfortability?

\$\endgroup\$
2
  • \$\begingroup\$ I don't think you have an option. You could either do it explicitly (your first way) or implicitly (the second), but I doubt you're going to find a mid point. Unless you have some kind of ent:"Point":SetPos(...)..which is almost the first method again. Maybe use the second method for common components? \$\endgroup\$ May 20, 2011 at 11:02
  • \$\begingroup\$ I think you may find use on gamedev.stackexchange.com/questions/12529/… I was trying to find a way to make my system as easy to use and compact as possible in terms of naming :) \$\endgroup\$ May 22, 2011 at 19:37

3 Answers 3

11
\$\begingroup\$

We have a similar situtation in our project, and we solved the problem by saving components (not functions) to LUA metatables. Basically, when we are creating an entity (or game object as we call them) on LUA side, code looks something like:

function createShip()
    ...

    self.transform = registerToComponent("transform")
    self.sprite = registerToComponent("sprite")

    ...
end

Now, we can use simply

entity.transform:setPosition(5.2, 4.8)
entity.sprite:setTexture("ship.png")

to set position (and texture). And we are totally happy with this!

(And actually I think this is better than having just entity:setPosition and entity:setTexture since when you have lots of components, resulting entity API would be just a big mess.)

\$\endgroup\$
4
\$\begingroup\$

The fundamental problem here is that you've exposed the component system to the API. You need to encapsulate that stuff behind your interface.

\$\endgroup\$
0
\$\begingroup\$

I haven't worked with Lua in a while, but couldn't you let your components themselves change the entity interface through the Lua wrapper (last time I used Lua in a game was in 2005, the wrappers must have evolved since then)?

By having it at the components level, you could have your position component register a "SetPos" function on the entity that calls the component directly and have a JointMotor component register an object in entity with a function "SetEnabled", this way it's "data driven" and support both ent:SetPos(123, 456) and ent:JointMotor:SetEnabled()?

As long as the registering of subobjects and functions validates that there is no name clash, you should be alright.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .