• Advertisement
Sign in to follow this  

Best Way to Embed Lua

This topic is 2997 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello everyone, I am attempting to embed lua into my game. I am currently using luabind and it's going great. However my question is what is the best way to embed it? I want to use Lua to control enemies/characters/levels things of that nature. I know how to take, say for example an enemy class with getters and move functions and make them visible to lua. But should I open a new lua state for each enemy? For my list of enemies? I'm not sure how to approach giving lua some control over large amounts of objects. I would like it to be as efficient as possible. If anyone could give me any pointers on how to design the program I would appreciate it.

Share this post


Link to post
Share on other sites
Advertisement
You don't need more than one LUA state in your game.

The way I do it is by using the pointers to the objects I want to control as "handles" in LUA - they are passed back and forth with the lua_pushlightuserdata/lua_touserdata functions. When some function is called (like a callback or something), my object pointer is passed to LUA. My object manipulation functions exposed to LUA take this "handle" as a parameter so the application can know which object I want to work with.

I'm not sure if there is another way of doing this that might be safer, but this works for my purposes.

Share this post


Link to post
Share on other sites
A state per enemy is excessive and makes it hard to exchange data from one state to the next without using a plugin from Luaforge.
Quote:
I would like it to be as efficient as possible
I am not going to pimp my own work, but if speed is something you are after then from my tests Luabind is the wrong library to be using. As Badgerr pointed out the most efficient yet less user friendly way is to use object handles, this could be light user data or entity id's.

Share this post


Link to post
Share on other sites
Thanks for the replies, pardon me for being completely ignorant on this subject... So I attempted to implement a simple Lua based particle system. The idea is that the user can change how particles are created, and how they are updated from lua by defining two functions in a lua file.

I have it working at the moment, the following lua code executes.


luaL_dostring(luaState,
"function updateParticle(p)\n"
"p.color.a = p.color.a-5\n"
"end\n"
"function spawnParticle(system)\n"
"p = system:createParticle()\n"
"p.life = 50\n"
"p.width = 50\n"
"p.height = 50\n"
"p.color.r = 255\n"
"p.color.g = 155\n"
"p.color.b = 55\n"
"p.color.a = 255\n"
"p.xVel = math.random(-2.2,2.2)\n"
"p.yVel = math.random(-2.2,2.2)\n"
"end\n"
);





So is this alright? I'm reluctant to feel that because it works at the moment that it is the correct way to do it. I guess I'm not going for optimum speed but rather ease of code while maintaining decent frame rates.

So with the current code, each particle system would have a string of code associated with it, and it would make a call to dostring to set the current functions. Then the particles update by making calls to say for example...


luabind::call_function<void>(luaState, "updateParticle", p);





And it seems that if doString is called multiple times, and functions have the same name then it picks the most recent? Should the lua state be cleared or anything? I have a feeling calling luaL_dostring multiple loops isn't the way to do it (hence why I thought having multiple lua states might be useful, just define each custom function once in each state).

If I renamed the function for each different particle file and ran toString in the initialize phase would that work? For example having/calling updateParticle[fileName] as the function name?

[Edited by - evilsanta on December 7, 2009 4:51:14 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by dmail
A state per enemy is excessive and makes it hard to exchange data from one state to the next without using a plugin from Luaforge.
Quote:
I would like it to be as efficient as possible
I am not going to pimp my own work, but if speed is something you are after then from my tests Luabind is the wrong library to be using.


Note that the performance of luabind has drastically improved for the next version, 0.9, which is approaching a stable state at http://github.com/luabind/luabind/tree/0.9.

--
Daniel Wallin

Share this post


Link to post
Share on other sites
My blog should help, if you go to my first couple posts you will see a presentation i made about lua and architecture. i would go into it here but the video and posts explain it in pretty good detail.

Share this post


Link to post
Share on other sites
Quote:
Original post by AverageJoeSSU
My blog should help, if you go to my first couple posts you will see a presentation i made about lua and architecture. i would go into it here but the video and posts explain it in pretty good detail.


Thanks for the video, very interesting stuff. So you kinda talked about this in the video, but I don't want to be passing objects to Lua (like in my code above)? I guess my question is, what should I be doing in my update loop? And what should I be initializing.

At the moment, I bind my classes in the init phase. Should I be calling do_string (or some equivalent) during the update? The code I posted above works, but I can only call update 20 times or so per iteration before my framerate dies.

[Edited by - evilsanta on December 8, 2009 3:03:52 PM]

Share this post


Link to post
Share on other sites
The main difference between your code and my code is that the main graphical stuff updates every frame at the native level. Lua just has a set of functions to work with the things.

Camera for example updates every frame with its matrix at the native level. (its a array of cameras and the active camera is what is used in rendering hence the id)

in lua i have a set of functions that take an ID of the camera (can be an actual instance of it but again this defeats the purpose of the architecture like i described in my errata) and pass that id to a native function that tells the camera to move to xyz point. lua doesnt really update the camera... it just tells the engine to move the camera and then the engine updates it and moves it accordingly during update.... (really the move function just adds an animator to the cameras animator stack, which gets evaluated every update).

Share this post


Link to post
Share on other sites
Quote:
Original post by evilsanta
The code I posted above works, but I can only call update 20 times or so per iteration before my framerate dies.


Seeing as this is for particles and they are normally created in large numbers I suspect the following line of your code is the problem

"p = system:createParticle()\n"


It should be written

"local p = system:createParticle()\n"


In Lua when you declare a variable and do not mark it local then it is global and therefore the garbage collector never cleans it up or the C++ Luabind "class_" and all its members. IIRC that it what it is called in Luabind yet I may be incorrect here. It is good Lua programming practice to declare all variables local unless this is not what you want them to be.


Offtopic:
Quote:
in lua i have a set of functions that take an ID of the camera (can be an actual instance of it but again this defeats the purpose of the architecture like i described in my errata) and pass that id to a native function that tells the camera to move to xyz point. lua doesnt really update the camera... it just tells the engine to move the camera and then the engine updates it and moves it accordingly during update.... (really the move function just adds an animator to the cameras animator stack, which gets evaluated every update).

Out of interest how does your C++ Lua registered functions know of your class instances, for example the "engine". I have not looked at your blog or the video which you mention yet I would assume it is one of three ways if you are using raw Lua.
1) You stuff the instances in the Lua state's registry and pull them out inside the registered functions.
2) Your instances are global.
3) You are using a monostate pattern and the functions and instances are static to a structure.

Share this post


Link to post
Share on other sites
Quote:
I have a feeling calling luaL_dostring multiple loops isn't the way to do it (hence why I thought having multiple lua states might be useful, just define each custom function once in each state).

By this do you mean that each buffer is being loaded for each particle at every iteration? If so then I would say this is the wrong approach to take.

Quote:
Note that the performance of luabind has drastically improved for the next version, 0.9, which is approaching a stable state at http://github.com/luabind/luabind/tree/0.9.

I look forward to the improvements that you are making, although I find it funny that you are willing to make a post about these yet not willing to help the OP who is using your library :)

[Edited by - dmail on December 9, 2009 5:29:54 AM]

Share this post


Link to post
Share on other sites
Thanks for the help everyone. So im trying to grasp how exactly I should handle multiple files. For the particle example, I would like a script programmer to create a new LUA file with certain methods such as spawnParticle for initializing particles, and updateParticle for updating.

I could just call tostring at the initialization phase, but if there are multiple particle files then they get over-ridden since all the functions have the same name.

Just for kicks, I made a function which searches through a Lua file and appends the filename onto the function name. This allows me to handle multiple functions of the same name. But I am still encountering the problem with it dieing fairly quickly. I am calling


luabind::call_function<void>(luaState, "updateParticle", p);



for each particle. Would it be superior to pass a list of particles to Lua? Or is this flawed design?

Share this post


Link to post
Share on other sites
Well the idea is sound but not scaleable. There is always a performance hit when going into and out of Lua into C++/C. Updating a single particle directly from script every frame your bound by the speed of Lua which proably can handle upwards to 10k particles per frame and still run 30fps, but what will kill you is calling 10k times into C++ from Lua.

Serveral solutions, let C++ hold the state of the particle and let Lua control it. So on C++ side you have particle class:

class Particle {
bool mActive;
Vector2D mPos;
Vector2D mVel;
};

like so, and Lua only changes the state of the particle mActive and in C++ you iterative over all active particles that frame to update. This way you don't need to call into C++ needlessly.

But if your changing the state of the particle every frame from Lua then you'll need to reduce that too more manageable levels. One way is to pass into C++ a table of all particle states you want to update that frame in one call vs 10k calls per particle.

Good Luck!


-ddn

Share this post


Link to post
Share on other sites
Quote:
Original post by dmail




Offtopic:
Quote:
in lua i have a set of functions that take an ID of the camera (can be an actual instance of it but again this defeats the purpose of the architecture like i described in my errata) and pass that id to a native function that tells the camera to move to xyz point. lua doesnt really update the camera... it just tells the engine to move the camera and then the engine updates it and moves it accordingly during update.... (really the move function just adds an animator to the cameras animator stack, which gets evaluated every update).

Out of interest how does your C++ Lua registered functions know of your class instances, for example the "engine". I have not looked at your blog or the video which you mention yet I would assume it is one of three ways if you are using raw Lua.
1) You stuff the instances in the Lua state's registry and pull them out inside the registered functions.
2) Your instances are global.
3) You are using a monostate pattern and the functions and instances are static to a structure.



it is 1 and 2.

I use Luna to push my one instance of the engine at startup, and have a set of API functions that can be called in lua to do all kinds of things (create objects, lights, cameras, particle emitters, move all of the above, and respond to/fire events from all of the above). EDIT: Oh and for all other things i use an ID/hash table system. each unique thing (camera, game object, light, etc) has its own pool of IDs with a hash table used to grab when the engine needs to animate or do something to them. I realize this may not be the absolute ideal thing to do, but it follows the architecture well.

For multiple files i use Lua's Module system, which i comment about on my blog as well.

It is a $@&@&% to get working, since it is not designed well. BUT, it does provide modularity for your scripts, so you can have a light table in a light.lua file that you can import and copy and use as a light. (again this is dependent upon HOW you decide to embed and use lua).

Share this post


Link to post
Share on other sites
Quote:
Original post by evilsanta
I could just call tostring at the initialization phase, but if there are multiple particle files then they get over-ridden since all the functions have the same name.

Just for kicks, I made a function which searches through a Lua file and appends the filename onto the function name. This allows me to handle multiple functions of the same name. But I am still encountering the problem with it dieing fairly quickly. I am calling


This is where Lua's table system and being able to create instances comes into play.

There is no reason to treat Lua any differently to other programming languages in that you load the code once and call it multiple times with different parameters.

If you are serious about using Lua then I suggest you read the Lua programming guide which will teach you how to do things like this properly.
You can either buy a copy of the latest (Lua 5.1) or read the Lua 5.0 version for free online.

btw, and this is aimed at others in this thread (and in general), it is "Lua" not "LUA". Saying otherwise is wrong.
Quote:

"Lua" (pronounced LOO-ah) means "Moon" in Portuguese. As such, it is neither an acronym nor an abbreviation, but a noun. More specifically, "Lua" is a name, the name of the Earth's moon and the name of the language. Like most names, it should be written in lower case with an initial capital, that is, "Lua". Please do not write it as "LUA", which is both ugly and confusing, because then it becomes an acronym with different meanings for different people. So, please, write "Lua" right!

Share this post


Link to post
Share on other sites
Alright so I have been experimenting with a lot of different things. I am starting to think that I should either have most of the work be done in Lua or only simple things such as events. Just to limit the amount of going in and out of Lua to C++.

I still have yet to pass a table of all particles that need updating so Lua can do all of them in one go. Does anyone know how I can pass from C++ to Lua a table of objects (preferably with Luabind)? I have been doing some research and it seems like it is fairly easy to do if you are using Lua by itself and just passing a table of userdata. However I like the simplicity Luabind offers... I might have to check out other libraries I guess.

I'll keep at it, but is it even a common thing to do? It seems like most games out there have events handled in Lua such as onHit, onCollide, etc. etc.. Is it even feasible to want to do what I want? That is to have some Lua control over all my objects that executes every iteration?

Share this post


Link to post
Share on other sites
My own personal take on this is that Lua should be used to;

- handle the configuration of emitters
- handle the starting and stopping of emitters
- (maybe update position information, although having them 'attached' to something else would get around this need).

And thats pretty much it.

Once started and emitter would be updated by the internal engine until such time as it dies naturally or it is stopped in some manner.

Share this post


Link to post
Share on other sites
Quote:
Original post by phantom
My own personal take on this is that Lua should be used to;

- handle the configuration of emitters
- handle the starting and stopping of emitters
- (maybe update position information, although having them 'attached' to something else would get around this need).

And thats pretty much it.

Once started and emitter would be updated by the internal engine until such time as it dies naturally or it is stopped in some manner.


Totally agree on this one, Lua is not meant to be involved in the rendering or updating of something like a particle.

really what lua would do is tell the emitter what particle to emit and where to go... maybe some physics input (Init), and then tell the engine to create a particle emitter with that description in spot xyz. Lua should never update an individual partical.

Think of lua as a user of your engine. It wants to use the things you give it, and not have to DO anything to what you provide.

Share this post


Link to post
Share on other sites
Don't use dostring().

The way you are doing it with dostring(), Lua has to compile that before it runs it every time. so that will be a huge hit to performance.

The way you should do it is you should have a bunch of files: particlesys.lua, menu.lua, game.lua etc that when run, create functions and put them in the global scope.Then when you initialize your app, call dofile(state, myluafile) and it will run that file to create those functions (if the code is written properly). then at any other time, you can call those functions because they are global.

As for best architecture for embedding, you'll have to figure that out. userdata and lightuserdata are useful. I highly recommend reading the reference and Programming in Lua for the idioms for this.

I personally do my data structure in lua (the big list of objects particles etc) with each object represented by a table with some fields for scripting and a userdata with metamethods for the physics stuff. All the phys stuff written in C. I am planning to move the data structure to C, with a table in lua mapping addresses of game objects to their scripting table. Do whatever is simplest and easiest. Don't be afraid to use tables, they are surprisingly fast.

hope this helps

Share this post


Link to post
Share on other sites
Ahh I see, I just need to design my particle system to be sophisticated enough so that lua doesn't need to update it.

Either way, thanks for all the replies everyone... I should be able to design a good system involving Lua now.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement