Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

Translation: Performance loss issue with the use of lua_call function series

A topic by Yanxiyimeng created Aug 13, 2023 Views: 220 Replies: 8
Viewing posts 1 to 3

Dear YelloAfterLife,

Hello! I'm working on adding external mod support to my game. 

When I create more monsters or player projectiles for the game, the performance cost of using lua_call to invoke Lua script functions in the step event becomes too high.

 Originally, the game runs at 2000 frames per second, but when there are more than 400 bullets in the game scene, the frame rate drops quickly (down to 20 fps). 

Is there any way to optimize this situation? 

I tried using object pools, but I couldn't reset the luaState (Is it possible to add an additional lua_state_reset() function to clear and restore the luaState's code content?). 

Regardless, the performance cost of lua_call is still significant, especially considering that there are more event functions for bullets in the mod. If I enable and call all of them, the game performance would be unbearable (it's terrifying). Do you have any suggestions? 

Thank you.

Best regards,

This is just the cost of calling the Step event for each bullet. If more script functions are added, the game will freeze completely (although I can't rule out the possibility that my computer is a bit slow, but the overhead is a bit excessive) 

(TAT)

Developer

Hello,

Performance will depend on what exactly you are doing - most of the cost comes from calling Lua functions in GameMaker and calling GameMaker functions in Lua (crossing the GameMaker/Lua border).

If you know how to use Visual Studio, you can compile the new version of Apollo - that is as fast as this currently can be, I believe.

Lua does not have a way to clear states (or even metatables) in general, but you probably shouldn’t create a new state for every instance - usually games use one state per mod. Something like this, for example:

function onCreate(gml_instance)
    -- 
end
function onStep(gml_instance)
    -- 
end
-- ...

Thank you for your response. I understand now. I have another question. For the Windows platform, I need to use `require` to import other Lua script functions for convenient development. However, this method does not support non-ASCII paths. I tried to compile a version that supports non-English paths myself and it worked successfully. Can support for non-English paths be added in Apollo v3?

In general, Apollo does not support passing non-English strings, such as when using `lua_add_file` to add a file with a non-English path. This often results in a file not found error and returns '0' (the same applies to `lua_add_code`).

Just like this:

lua_add_code(state,package.path="+"'"+string_replace_all(ASSETS_DIRECTORY+"Scripts/","\\","/")+"?.lua"+"'");

Developer (1 edit)

That is a Lua limitation - it uses fopen (which isn’t Unicode-aware on Windows) everywhere:

https://github.com/lua/lua/blob/ea39042e13645f63713425c05cc9ee4cfdcf0a40/lauxlib.c#L790

I am not currently in a position to fix bugs in Lua, but if you find a Lua fork that fixes this, you can compile Apollo while using it instead of original Lua.

Thanks, excuse me, does the v3 version optimize the performance of function calls? When using Lua, it is inevitable to call functions from GameMaker (such as to check if a key has been pressed, or to determine if two GameObjects have collided), for these operations, the performance overhead is too large (TAT)

Also thank you very much for your tireless efforts to answer a noob's question! XD

Developer

As mentioned earlier, yes - GameMaker now allows to read/write GML values on C++ side (like this), which makes a number of actions faster as far as this extension goes.

Thank you very much for your reply, which makes me look forward to the release of the v3 version,and recently, I ran into a small issue:

setmetatable(_G, {
    __index = function(s, n)
        if(type(s)=="table")then
            <Call GML Function ...>
        end
         return _G[n]
    end
}
);

I want to monitor user access to the Lua script's Table with this code, but it doesn't work

When calling the GML function.

The console prompts the following message :PANIC: unprotected error in call to Lua API (attempt to yield from outside a coroutine)

What is the reason for this and how can I solve this problem?


Developer

That’s the limitation of the approach used in V2 - to call GML code, Lua state is paused, but Lua does not support pausing states in some situations (such as in a meta-methods).