|
Paul Du Bois wrote: [...snip...]
In our game, the dispatcher is written in C++. I handle both a Preemptive and Cooperative multitasking within the same script. For Cooperative, i have functions bound that call lua_yield on the coroutine, and can either yield for X seconds or N frames (at a later date, also yield until X condition). For preemptive, i use lua_hooks. I break into C++ every N instructions, check to see if the quantum is up, and yield if it is.Is it possible to re-enter a script with a prior context so that the lua_State of one function can be used as the lua_State of another?Yes; read up on coroutines. For example, this is what we do in our engine right now: function Ob:onTick(dt) local fn = rawget(self, 'current_statefunc') if fn then local bSuccess, result = coroutine.resume(fn, self, dt) if not bSuccess then Tracef("Error running state '%s':\n%s", self.current_state, result) self:setState(nil) else if coroutine.status(fn) == "dead" then self.current_statefunc = nil end end end end onTick gets called every frame/update/whatever. Often, anyway. An object can call self:setState() on itself, which among other things, sets up a particular function to be resumed every tick. The function runs to completion or until it yields. The net effect is a system where every object can pretend it has its own thread of execution. Almost all of our object/script system is implemented in lua at the moment (a switch from Psychonauts, which did stack manipulation and a bunch of other stuff). This is very nice, as it allows you to play with various semantics and implementation strategies. When you have something you like, you can "freeze" it into C/C++ if you like, and if it's worth it. p
I can switch between both runmodels in the same script, so, for example, if block of script needs to execute atomically (as in, on the same frame), i change the runmodel to cooperative, and then change it back to preemptive.
An advantage of having this system is that I can pause a script, make it start again, reload it, and kill it without a problem.
Also, an implementation note: in the cooperative runmodel, i also use lua_Hook to make sure that the script doesn't do infinite loops and freeze the game. If it executes without yielding for more than X time, assert and then pause the script.
The concept of this was inspired by Matthew Harmon, from eV Interactive Corporation, and was featured in Game Programming Gems 5.
Hope this helps. // David Morris-Oliveros // Camera & Lua Coder // david@teambondi.com