I believe that what keeps people from playing NS2 is not the performance, but the overly punishing game mechanics that prevent many new players from sliding easily into the game. Face it, NS2 is a brutal game for new players, with a steep learning curve and limited rewards to encourage these new players to keep playing. We've learned a lot making NS2, that our future projects will certainly benefit from, but at this point, to make a big difference to player counts NS2 would probably need to be reworked from the ground up.
Totally agree. For newbies, waiting 10 minutes to get a fade or an onos and then dying 10 seconds later is really disheartening. There's also no progression system in place, which makes a lot of players feel like they aren't accomplishing anything. I personally view these attributes of NS2 as an asset, but I could see how many players would disagree.
I'm pretty sure it's impossible to design a video game that appeals to both the hardcore audience (most ns2 players) and the "casual" audience (the bulk of paying consumers).
Has UWE done anything with NS2 Since build 249? Just funny to see you guys arguing over how much money was spent where. Then to throw out a figure as large as 100K for a map. That is scary and sad at the same time. That speaks to the Spark engine. Don't worry though we spent the better part of 7 years developing a game engine that will allow good mods/ maps to be produced in a timely manner. I guess not!!!
I feel sorry for the stand alone combat guys they had the right idea then some how reverted the cues from their senses. Spark engine is just really bad period. That is the reason there are very few 3rd party mods 1.5 years later after official release.
Now in regards to fixes which I know UWE won't do. Thank you 3rd party modders.
Marine commander- Allow exo's to be droppable single & Dual
Dual rail gun- Allow both guns to be fired at same time.
Aliens commander- revamp the lifeform drop parameters. Gorge 2 biomass, lerk/fades 3 biomass, onos 6 biomass. Keep the cost the same.
Lifeform abilities- Need a biomass revamp as well. Leap should be biomass 3, spores should be 4 and umbra 5. Might even think about moving the fade special attack way down so it actually is used. Pretty much need to see these shuffled around so they are actually used usefully in game play outside of people just messing around.
Annoying bug- Refinery still get stuck on IP's when marines spawn in either containment or turbine.
Please UWE make an NS3 with a decent engine, runing smooth like CS:GO and you will have a much more larger playerbase. I really love NS2, i still play it and pay for the dlc (new kodiak dlc, reinforced...) because i think u deserve it for your work but... im reallist, NS2 with his performance cant be more than already is, unfortunately
You'll never have a large playerbase when most ISPs can't host a 3.6ghz+ server.. Look at TF2 and CS:GO, huge amount of servers on some pretty basic servers running fine.
Regarding the new map vs. fixes/perf thing, that is actually a fair point. Yes, we chose to spend a lot of the donated money on a new map. Maybe we should have spent it on contracting one programmer (probably fsfod) to optimize the game for 2-3 months? That's how long it probably would have taken to get a significant bump in perf - it would basically involve changing 50% of Lua code, everywhere. But, that still would've been risky - would the perf actually get much better after that? How much better? How many MORE bugs would it introduce? It would certainly break ALL mods. So, at the end of the day, you can see why making a new map is a much safer bet than a complete overhaul of the code.
We have definitely learned from the performance woes of NS2 (yes, we absolutely acknowledge it as an issue), and for future projects that use Lua, we will architect things from the ground up with LuaJIT in mind. As for NS2, unfortunately, it's hard to make those kind of changes this late with a gigantic code base.
How mechanical is the process of refactoring to take advantage of LuaJIT? Is it the sort of thing you can do with only making local changes to the codebase? Do you guys have a profiler that you trust? Is there enough test coverage that you'd have a way of trustIng community contributions?
I'd really enjoy working on this periodically if its a tractable thing to do. I'm not familiar with either Lua or LuaJIT, but if its just a tedious process rather than a difficult one, it wouldn't be hard to learn.
OK i can dig in to some serious LuaJIT details here.
The thing about LuaJIT is that while it can do amazing things in Lua-land, any benefits are completely nullified if you go back and forth between Lua and C++ land often. NS2's Lua-API, unfortunately, does this....basically all the time. Any time you access ent.origin? Hits C++. This was originally done for many good reasons, such as making OOP-like features possible, making networked variables very easy to implement, etc. etc. etc. Unfortunately, this style of interaction between C++ and Lua, with frequent back and forths, means that LuaJIT cannot do much JIT'ing at all (which is where most of its magic comes from). Also things like raytrace-callbacks would need to be completely re-architectured.
So, this is certainly all possible, but my guess is it would be at least 2 months of engineering + bug fixing, not to mention how it would affect the rest of the team working on other things simultaneously. In the "LuaJIT build", we were able to do many things to reduce this back-and-forth, such as switching most math operations to be Lua-only (ironic isn't it?), but there is plenty of other stuff that is not so easy. I myself spent a good 2-3 weeks on the initial LuaJIT integration, working through some of these API issues, and then fsfod took over with a lot of his own crazy under-the-hood stuff. And I'm sure fsfod can elaborate, or tell me that I'm completely mis-remembering the issues
In any case, it was just hard to justify spending tons more time on this. It could be one of those things where shit just gets more and more hairy the more you get into it. It is not a simple effort in ==> performance out deal. Hell, things in game dev rarely are.
More specifically, no we don't have a great sample-based Lua profiler. We have an in-game profiler for in-code sections, which is fine for some things, but nothing like Intel VTune. Test coverage...we don't have any automated testing for NS2, as we typically rely on play testers for QA. I would say it is both a tedious and difficult task, where you're constantly worried about introducing bugs because you're ripping out some fundamental things.
The thing about LuaJIT is that while it can do amazing things in Lua-land, any benefits are completely nullified if you go back and forth between Lua and C++ land often. NS2's Lua-API, unfortunately, does this....basically all the time. Any time you access ent.origin? Hits C++. This was originally done for many good reasons, such as making OOP-like features possible, making networked variables very easy to implement, etc. etc. etc. Unfortunately, this style of interaction between C++ and Lua, with frequent back and forths, means that LuaJIT cannot do much JIT'ing at all (which is where most of its magic comes from). Also things like raytrace-callbacks would need to be completely re-architectured.
Do you think statically compiling via llvm would have much of an impact? Does that have the same sort of issues at the Lua/C++ boundary or can the compiler deal with it then? You'd have to totally rethink how mods work, but maybe it would be worth it?
Thanks for shedding some light on the technical part of the issue @SteveRock.
Makes a lot of sense.
As I mentioned in my post earlier though.. if the game is ever to go F2P as TF2 did.. you'll have to start thinking about performance to support all those new players.
At the moment I don't think it would be acceptable for the vast majority of the people running on potatoes that would be playing. Current servers still have to have extremely high specs in order to run NS2 stable and.. that's not even touching on the client side of things.
If you don't go F2P then all I see from these patches like Kodiak is just barely hanging on before the inevitable end.. rather than a plan to keep the game going and growing indefinitely. I would hate to see NS2 go the way of NS1.. my childhood game gone down the drain of the interweb tubes.
When arguing about performance one way or the other, I think it would be very important to note the feel and presentation of things rather than just talking about raw performance and squeezing out maximum amount of frames.
When I jump to NS2 from games with other engines, the sounds feel different, the animations sometimes feel different, the collisions often feel different. All this contributes both to accessibility and fun factor of the game. A lot of things in the game are manageable and passable as they are, but that's roughly it. They don't give me that same kind of enjoyment of precision, reliability, finesse and possibilities as playing something like Quake 3/Live or even certain aspects of Source engine games.
A lot of the same goes for the existing feautres and customization available for the game. As far as I've understood, the keybindings are still missing some options, you have to tinker with workshop just to change your crosshair and so on. Last time I played wasn't any obvious way to hear your own microphone voice anywhere so you can't tell how your teammates hear you.
To me, all this is what makes NS2 really hard to pick up - even when you're running sufficient amount of frames and willing to grasp difficult concepts. I don't think the discussion should be as much of raw performance vs extra content as it should be refining the existing content - including improved performance - vs completely new content.
@SteveRock If you'd want to use the Spark engine in any future project again, wouldn't you have to sort out these issues sooner or later anyway? Or is it just NS2 that uses the engine in that bad C++/Lua back and forth way?
@SteveRock If you'd want to use the Spark engine in any future project again, wouldn't you have to sort out these issues sooner or later anyway? Or is it just NS2 that uses the engine in that bad C++/Lua back and forth way?
@SteveRock If you'd want to use the Spark engine in any future project again, wouldn't you have to sort out these issues sooner or later anyway? Or is it just NS2 that uses the engine in that bad C++/Lua back and forth way?
yes, absolutely. but we wouldn't have to rework ns2 to do it right for a new game.
The thing about LuaJIT is that while it can do amazing things in Lua-land, any benefits are completely nullified if you go back and forth between Lua and C++ land often. NS2's Lua-API, unfortunately, does this....basically all the time. Any time you access ent.origin? Hits C++. This was originally done for many good reasons, such as making OOP-like features possible, making networked variables very easy to implement, etc. etc. etc. Unfortunately, this style of interaction between C++ and Lua, with frequent back and forths, means that LuaJIT cannot do much JIT'ing at all (which is where most of its magic comes from). Also things like raytrace-callbacks would need to be completely re-architectured.
Do you think statically compiling via llvm would have much of an impact? Does that have the same sort of issues at the Lua/C++ boundary or can the compiler deal with it then? You'd have to totally rethink how mods work, but maybe it would be worth it?
what exactly do you mean? it would depend on the exact details of the compiling...it would at least require a new description of the API?
yes, absolutely. but we wouldn't have to rework ns2 to do it right for a new game.
I see. Then it would be great if you somehow could uncouple the game and it's engine. If you enhance the engine, all games using it could benefit. Like when Source got Orange upgrade. The train has departed for NS2 though.
yes, absolutely. but we wouldn't have to rework ns2 to do it right for a new game.
I see. Then it would be great if you somehow could uncouple the game and it's engine. If you enhance the engine, all games using it could benefit. Like when Source got Orange upgrade. The train has departed for NS2 though.
When Valve did some work on the Source engine, they have to do some work on their game code too... It breaks a lot of things when you change Source version.
It would be very hard to do a completely modular engine without needing changes elsewhere.
what exactly do you mean? it would depend on the exact details of the compiling...it would at least require a new description of the API?
I was thinking just producing a single monolithic binary where the lua is compiled down to native code. If luajit has to fall back to interpreting near native calls and that's the slow part, then this would at least fix that. https://code.google.com/p/llvm-lua/ If marshalling data between lua and native code is the slow part then it might not help much, because I would presume that would still be going on. Another option then would be to use llvm for an intermediate output for both the C++ and Lua, and then compile from both to native code simultaneously. I don't know whether that's possible from how the tools are set up today, but at least theoretically this would allow optimizations that cross the boundary of the C++/Lua code, because anything past that point in llvm doesn't care about the source language.
what exactly do you mean? it would depend on the exact details of the compiling...it would at least require a new description of the API?
I was thinking just producing a single monolithic binary where the lua is compiled down to native code. If luajit has to fall back to interpreting near native calls and that's the slow part, then this would at least fix that. https://code.google.com/p/llvm-lua/ If marshalling data between lua and native code is the slow part then it might not help much, because I would presume that would still be going on. Another option then would be to use llvm for an intermediate output for both the C++ and Lua, and then compile from both to native code simultaneously. I don't know whether that's possible from how the tools are set up today, but at least theoretically this would allow optimizations that cross the boundary of the C++/Lua code, because anything past that point in llvm doesn't care about the source language.
No idea what this means, but it sounds like its worth investigating if there is a chance to increase the speed the Lua bits talk to the C++ bits.
When Valve did some work on the Source engine, they have to do some work on their game code too... It breaks a lot of things when you change Source version. It would be very hard to do a completely modular engine without needing changes elsewhere.
Yes, however Source engine is still way more modular than Spark. If Spark had been built with modularity in mind (as Source was: http://en.wikipedia.org/wiki/Source_(game_engine)) , the issues we have now wouldnt be so striking.
what exactly do you mean? it would depend on the exact details of the compiling...it would at least require a new description of the API?
I was thinking just producing a single monolithic binary where the lua is compiled down to native code. If luajit has to fall back to interpreting near native calls and that's the slow part, then this would at least fix that. https://code.google.com/p/llvm-lua/ If marshalling data between lua and native code is the slow part then it might not help much, because I would presume that would still be going on. Another option then would be to use llvm for an intermediate output for both the C++ and Lua, and then compile from both to native code simultaneously. I don't know whether that's possible from how the tools are set up today, but at least theoretically this would allow optimizations that cross the boundary of the C++/Lua code, because anything past that point in llvm doesn't care about the source language.
I doubt this would help without - again - a huge overhaul of the API (and thus the entire Lua code base). This general approach of statically compiling Lua is a bit questionable, since as a dynamic language, so much of it is unknown at compile time - I really don't see it being very successful (and, this is why LuaJIT has become the dominant force in high-perf Lua - it doesn't do it statically). And plus, the API/VM-management layer the engine runs is...haha yeah no way you're optimizing through that. I'm not gonna prove it, but it's probably impossible.
When Valve did some work on the Source engine, they have to do some work on their game code too... It breaks a lot of things when you change Source version. It would be very hard to do a completely modular engine without needing changes elsewhere.
Yes, however Source engine is still way more modular than Spark. If Spark had been built with modularity in mind (as Source was: http://en.wikipedia.org/wiki/Source_(game_engine)) , the issues we have now wouldnt be so striking.
No Spark is actually quite modular, and that's why we're able to rip the Lua part out while still re-using most of the engine for future project(s). If Source totally reworked their game play API, it would still break a shitload of mods and previous games. They haven't done that, and haven't needed to apparently. No, our mistake (in hindsight) on Spark had nothing to do with modularity - it was just the way we used Lua.
In the "LuaJIT build", we were able to do many things to reduce this back-and-forth, such as switching most math operations to be Lua-only (ironic isn't it?), but there is plenty of other stuff that is not so easy.
That is crazy. Common knowledge I always thought was that your vector math libs should be doing the math in c-land. Does this mean it would generally be better to do a big write of data into lua tables at the start of the frame, operate on it all in the luavm without switching, and then read out of the lua tables again at the end of the frame to update the world/clients?
I'd love to know more of which things are better performance-wise to remain in code vs be run exclusively through Lua (when using luajit).
That is crazy. Common knowledge I always thought was that your vector math libs should be doing the math in c-land. Does this mean it would generally be better to do a big write of data into lua tables at the start of the frame, operate on it all in the luavm without switching, and then read out of the lua tables again at the end of the frame to update the world/clients?
I'd love to know more of which things are better performance-wise to remain in code vs be run exclusively through Lua (when using luajit).
Well any Lua code that calls into engine the that in turn causes the engine to call back into Lua can never be jit'ed because of limitations with LuaJIT. This happens a lot with anything that results in a GetCoord of an entity
McGlaspiewww.team156.comJoin Date: 2010-07-26Member: 73044Members, Super Administrators, Forum Admins, NS2 Developer, NS2 Playtester, Squad Five Blue, Squad Five Silver, Squad Five Gold, Reinforced - Onos, WC 2013 - Gold, Subnautica Playtester
@fsfod@SteveRock So I guess it's safe to assume anything that calls the functions defined in the 'docs' folder ( all those json files ) is a callback to the engine?
@fsfod@SteveRock So I guess it's safe to assume anything that calls the functions defined in the 'docs' folder ( all those json files ) is a callback to the engine?
I may be remembering wrong, but I'm pretty sure it's even more than that...like every entity field access, like ent.health, hits C++ and probably does some network-variable-decoding stuff. Most of the explicit API functions we were able to convert to FFI, which LuaJIT can actually work with, but yeah, it's more.
That is crazy. Common knowledge I always thought was that your vector math libs should be doing the math in c-land. Does this mean it would generally be better to do a big write of data into lua tables at the start of the frame, operate on it all in the luavm without switching, and then read out of the lua tables again at the end of the frame to update the world/clients?
I'd love to know more of which things are better performance-wise to remain in code vs be run exclusively through Lua (when using luajit).
Well any Lua code that calls into engine the that in turn causes the engine to call back into Lua can never be jit'ed because of limitations with LuaJIT. This happens a lot with anything that results in a GetCoord of an entity
And I wouldn't even blame LuaJIT for this - they do actually provide an FFI thing that can get around this in limited cases. But basically, the Lua C/API allows you to do WHATEVER THE FUCK and it's just a fact of the universe that you can't optimize when you have no clue what might happen at any time.
Comments
Totally agree. For newbies, waiting 10 minutes to get a fade or an onos and then dying 10 seconds later is really disheartening. There's also no progression system in place, which makes a lot of players feel like they aren't accomplishing anything. I personally view these attributes of NS2 as an asset, but I could see how many players would disagree.
I'm pretty sure it's impossible to design a video game that appeals to both the hardcore audience (most ns2 players) and the "casual" audience (the bulk of paying consumers).
tdlr: i love you uwe, but i wanted more fps and server stability over content
This x1 bazillion
I feel sorry for the stand alone combat guys they had the right idea then some how reverted the cues from their senses. Spark engine is just really bad period. That is the reason there are very few 3rd party mods 1.5 years later after official release.
Now in regards to fixes which I know UWE won't do. Thank you 3rd party modders.
Marine commander- Allow exo's to be droppable single & Dual
Dual rail gun- Allow both guns to be fired at same time.
Aliens commander- revamp the lifeform drop parameters. Gorge 2 biomass, lerk/fades 3 biomass, onos 6 biomass. Keep the cost the same.
Lifeform abilities- Need a biomass revamp as well. Leap should be biomass 3, spores should be 4 and umbra 5. Might even think about moving the fade special attack way down so it actually is used. Pretty much need to see these shuffled around so they are actually used usefully in game play outside of people just messing around.
Annoying bug- Refinery still get stuck on IP's when marines spawn in either containment or turbine.
sorry bad english and Greetings!
OK i can dig in to some serious LuaJIT details here.
The thing about LuaJIT is that while it can do amazing things in Lua-land, any benefits are completely nullified if you go back and forth between Lua and C++ land often. NS2's Lua-API, unfortunately, does this....basically all the time. Any time you access ent.origin? Hits C++. This was originally done for many good reasons, such as making OOP-like features possible, making networked variables very easy to implement, etc. etc. etc. Unfortunately, this style of interaction between C++ and Lua, with frequent back and forths, means that LuaJIT cannot do much JIT'ing at all (which is where most of its magic comes from). Also things like raytrace-callbacks would need to be completely re-architectured.
So, this is certainly all possible, but my guess is it would be at least 2 months of engineering + bug fixing, not to mention how it would affect the rest of the team working on other things simultaneously. In the "LuaJIT build", we were able to do many things to reduce this back-and-forth, such as switching most math operations to be Lua-only (ironic isn't it?), but there is plenty of other stuff that is not so easy. I myself spent a good 2-3 weeks on the initial LuaJIT integration, working through some of these API issues, and then fsfod took over with a lot of his own crazy under-the-hood stuff. And I'm sure fsfod can elaborate, or tell me that I'm completely mis-remembering the issues
In any case, it was just hard to justify spending tons more time on this. It could be one of those things where shit just gets more and more hairy the more you get into it. It is not a simple effort in ==> performance out deal. Hell, things in game dev rarely are.
More specifically, no we don't have a great sample-based Lua profiler. We have an in-game profiler for in-code sections, which is fine for some things, but nothing like Intel VTune. Test coverage...we don't have any automated testing for NS2, as we typically rely on play testers for QA. I would say it is both a tedious and difficult task, where you're constantly worried about introducing bugs because you're ripping out some fundamental things.
Do you think statically compiling via llvm would have much of an impact? Does that have the same sort of issues at the Lua/C++ boundary or can the compiler deal with it then? You'd have to totally rethink how mods work, but maybe it would be worth it?
Makes a lot of sense.
As I mentioned in my post earlier though.. if the game is ever to go F2P as TF2 did.. you'll have to start thinking about performance to support all those new players.
At the moment I don't think it would be acceptable for the vast majority of the people running on potatoes that would be playing. Current servers still have to have extremely high specs in order to run NS2 stable and.. that's not even touching on the client side of things.
If you don't go F2P then all I see from these patches like Kodiak is just barely hanging on before the inevitable end.. rather than a plan to keep the game going and growing indefinitely. I would hate to see NS2 go the way of NS1.. my childhood game gone down the drain of the interweb tubes.
When I jump to NS2 from games with other engines, the sounds feel different, the animations sometimes feel different, the collisions often feel different. All this contributes both to accessibility and fun factor of the game. A lot of things in the game are manageable and passable as they are, but that's roughly it. They don't give me that same kind of enjoyment of precision, reliability, finesse and possibilities as playing something like Quake 3/Live or even certain aspects of Source engine games.
A lot of the same goes for the existing feautres and customization available for the game. As far as I've understood, the keybindings are still missing some options, you have to tinker with workshop just to change your crosshair and so on. Last time I played wasn't any obvious way to hear your own microphone voice anywhere so you can't tell how your teammates hear you.
To me, all this is what makes NS2 really hard to pick up - even when you're running sufficient amount of frames and willing to grasp difficult concepts. I don't think the discussion should be as much of raw performance vs extra content as it should be refining the existing content - including improved performance - vs completely new content.
It's just NS2. NS2 is written in LUA. (Afaik)
yes, absolutely. but we wouldn't have to rework ns2 to do it right for a new game.
what exactly do you mean? it would depend on the exact details of the compiling...it would at least require a new description of the API?
It would be very hard to do a completely modular engine without needing changes elsewhere.
I was thinking just producing a single monolithic binary where the lua is compiled down to native code. If luajit has to fall back to interpreting near native calls and that's the slow part, then this would at least fix that. https://code.google.com/p/llvm-lua/ If marshalling data between lua and native code is the slow part then it might not help much, because I would presume that would still be going on. Another option then would be to use llvm for an intermediate output for both the C++ and Lua, and then compile from both to native code simultaneously. I don't know whether that's possible from how the tools are set up today, but at least theoretically this would allow optimizations that cross the boundary of the C++/Lua code, because anything past that point in llvm doesn't care about the source language.
No idea what this means, but it sounds like its worth investigating if there is a chance to increase the speed the Lua bits talk to the C++ bits.
I doubt this would help without - again - a huge overhaul of the API (and thus the entire Lua code base). This general approach of statically compiling Lua is a bit questionable, since as a dynamic language, so much of it is unknown at compile time - I really don't see it being very successful (and, this is why LuaJIT has become the dominant force in high-perf Lua - it doesn't do it statically). And plus, the API/VM-management layer the engine runs is...haha yeah no way you're optimizing through that. I'm not gonna prove it, but it's probably impossible.
No Spark is actually quite modular, and that's why we're able to rip the Lua part out while still re-using most of the engine for future project(s). If Source totally reworked their game play API, it would still break a shitload of mods and previous games. They haven't done that, and haven't needed to apparently. No, our mistake (in hindsight) on Spark had nothing to do with modularity - it was just the way we used Lua.
I'd love to know more of which things are better performance-wise to remain in code vs be run exclusively through Lua (when using luajit).
Can you give some more info on what you'd do differently or ideas you have for an architecture that would better leverage luajit?
Well any Lua code that calls into engine the that in turn causes the engine to call back into Lua can never be jit'ed because of limitations with LuaJIT. This happens a lot with anything that results in a GetCoord of an entity
I may be remembering wrong, but I'm pretty sure it's even more than that...like every entity field access, like ent.health, hits C++ and probably does some network-variable-decoding stuff. Most of the explicit API functions we were able to convert to FFI, which LuaJIT can actually work with, but yeah, it's more.
If you want a good summary, read this thread: http://stackoverflow.com/questions/2588071/is-luajit-really-faster-than-every-other-jit-ed-dynamic-languages
And I wouldn't even blame LuaJIT for this - they do actually provide an FFI thing that can get around this in limited cases. But basically, the Lua C/API allows you to do WHATEVER THE FUCK and it's just a fact of the universe that you can't optimize when you have no clue what might happen at any time.
Multiple balance overhauls (which were annoying) and new content in reinforced. Also bug fixes and optimizations.