So I almost have a game done. I'm running some final balance/typo/bug checks, and one thing that has consistently stuck out to me is how the performance in the game just TANKS the longer you play it. Which is a downright weird thing to say about a text game.
This'll be a bit long, but please bear with me.
A large part of the game is team fights. You and up to 3 allies vs up to 4 enemies in turn-based combat. A lot of it's laid out like a puzzle; "which teammates do I want for this fight? How do I avoid THIS enemy attack?" etc.
Here's the performance issue: When you are IN the fight, the performance gets worse and worse the longer you play the game. So at the start you choose to shoot enemy 1 with a doubleshot. You go into a special 'This is what happens this turn' room and see:
You shoot Enemy1 twice! X damage! X damage! Ally1 puts a shield around Ally3! Ally2 heals Ally3 for X hp! Ally3 zaps Enemy1! X damage! Enemy1 does something. Enemy2 does something. CONTINUE HYPERLINK
And then you press the Continue hyperlink, the screen clears, you're brought to the 'choose your attack' room. And the cycle repeats.
The problem is, as time goes on, it begins to stutter. Pauses occur between lines, seemingly at random, regardless of what's happening in the actual fight. The worse the problem is, the longer these pauses are and there can even be multiple ones per new description. There's no rhyme or reason as to WHERE the pauses occur, not that I can tell even after using debug-prints statements.
These pauses also occur on the 'choose your attack' room, since the 'choose your attack' room generates its description via script. The description is generally as follows:
YOU 50/60 HP 30/75 Energy Ally1 60/60 HP 50/75 Energy Ally2 50/50 HP 35/100 Energy Ally3 100/150 HP 50/55 Energy Enemy1 900/999 HP 900/999 Energy ATTACKS Hyperlink MISC actions Hyperlink RUN AWAY Hyperlink
And there'd be random pauses at, during, and before various chunks of text.
As for how the fights work: I use a lot of Objects and Clones. When a fight starts, I make a clone of a FighterBaseObject that's in a DebugRoom, set its HP and Alias and etc, and move it to the Fight room. I repeat this for all enemies and nonpermanent allies (Permanent Ally FighterObjects are cloned at the start and are simply moved around).
This gives me a LOT of flexibility with the fights. I can even make robust buffs/debuffs by having a similar cloning habit with BuffBaseObjects moved into various FighterBaseObjects.
When a given object is no longer needed, I use destroy() to get rid of it, as opposed to Remove so there isn't a million useless objects from past fights just floating around.
Here are some things I know the issue isn't.
I know it's not one specific fight causing the problem. If I use my developer debug commands to instantly start Encounter 99, defeat that, Encounter 100, 101, and 102, then when I go into Encounter 103 the performance will be virtually unplayable.
But if I instead instantly go to Encounter 103, it's just fine until partway into the fight.
I know it's not my Fight Code being too complicated
After every character takes their turn, the game checks every clone of FighterObject, and every BuffObject in each FighterObject, and manipulates their attributes as needed with the state of the fight. Since there's a fair few 4v4 fights, I thought maybe it's just taking a while to process?
But no. Encounters 99,100,101,103 might all be 4v4s, but Encounter 6, for instance, is much simpler, so is Encounter 7. But if I go through those, the performance still becomes bad.
I'm reasonably certain it's not excessive generation/deletion of FighterObjects and BuffObjects by fights
If I developer-debug right into encounters 99-103, I get the slowdown issue.
But if I do not, if I play normally, walking around a bunch of rooms so that actual fighting is a minority of the play, and go through Encounters 1-4, then encounter 5 will still have terrible performance just like 103 does.
Now, this COULD be because of another Object clones I produce; you travel around in a spaceship through various solar systems, which I populate via CelestialObjectBase clones to create the stars and planets, and destroy() them when you change systems. But the amount of objects destroyed in this manner is MINUSCULE compared to how many FighterObjects and BuffObjects are destroyed when I go through encounters 99-103.
The only idea I have is that somehow the game stores every move you ever make, and over the course of a longer playtime slowsdown immensely for some reason.
I would seriously appreciate some help. This is an ambitious game for me, but this performance issue makes it unplayable; I cannot publish something in this state!
Launch Task Manager... watch the memory value...
It could be that you are using up your memory and the CPU it trying to get by on what's left...
Instead of cloning and destroying them, why not recycle them?
Keep a few copies, and change their stats as needed.
@DarkLizerd I have tried that before, the memory hovers at around 50-60% iirc, with no apparent relation to what's actively going on ingame.
I could recycle, but then what happens if you go from a fight with 4v4 to 4v1? What do I do with the remaining 3? What about any buffs those 3 had? What if I reuse those 3, what do I do with their buffobjects?
It just seems like such a hassle, for no benefit that I can find.
My first thought is whether the delay occurs the same on the desktop and online players.
(If it does, the issue is pretty easy to pin down, because timing is different between the two)
Sorry if you've already checked that.
How would I test the difference between desktop and online players? I'm editing it on the dowloadable version of quest, I cannot test it online? Unless there's some way of doing so that I am missing?
Bumping because still unsolved. I don't know, is this a frowned upon thing to do? I really want an idea of what to do.
could you create a sample game with just your battle code? Then we could recreate the problem.
@Pertex, alright, I've created a Performance Test game with what I believe are all the relevant parts. Though like I said earlier, I'm not actually confident that it's the battle code causing the problem.
no, its not the battle code, I dont get performance problems.
Does the problem appear while running a walkthrough? Perhaps at the same position when you start the walkthrough several times?
I didn't actually use a walkthrough for testing - never learned how. I had an optional "JumpAhead" function that fires at the start of the game, which brings you to a place in the game that I control ahead of time by altering the code.
It reads a DebugRoom.JumpList stringlist for stuff like "BeatEnemy1", "StartFinalMission" etc and does certain things.
I get the performance issue whether I use the JumpAhead or not, and when I do, where I jump has no impact on the issue.
To use a Walk-through
Go to your Tree Of Stuff and Scroll Down to the Bottom.
Above Advanced (depending on your set up) you'll see Walkthrough.
Through the GUI, Right Click on Walkthrough and Create A New Walkthrough.
3a. In CodeView. (see below)
<walkthrough name="Random"> <steps type="simplestringlist"> </steps> </walkthrough>
+ - / > O
The Circle records your choices. So click that and run through your game up to the point where the problem happens, then click STOP as normal and all your choices up to that point will be recorded.
Hit the PLAY button to rush through those choices each time :) and there's your Walkthrough.
Thanks Anonynn. Sadly through the looks of it, the walkthrough wouldn't be much help here, as the game as fairly open ended and has a small amount of variance; sometimes a fight may last 5 or 4 turns depending on how enemies RNG dodge, and I can't see any way to add conditions to check what's going on in the game.
And as I mentioned earlier, the problem isn't something that just suddenly happens out of nowhere. It's a steady decrease in performance over time, eventually becoming worse than I can bear.
I'm not as knowledge-able as all of you guys (io, mrangel, pixie, pertex, etc), but here's my thoughts:
with modern machines/CPUs/memory-sticks, etc, bad/slow performance can only be caused in a few ways:
the software (quest) being used itself has problems (not enough memory allocated to it from the computer memory, for it to then allocate enough memory for peoples' games, etc software-hardware stuff, or see #2-4 below for the software itself's own internal coding)
too much data: usually this culprit is error'ed/bugged or inefficient, scripting and/or game design, involving cloning (creating more data)
too much operations: can be any number of error'ed/bugged or inefficient, scripting and/or game design, but generally (easiest suspect) it's often due to (near infinite or infinite) looping and/or usage of recursion and/or doing too many levels/layers/nesting of array/list/dictionary 'foreach-ing'/iterations
the software doesn't allocate enough memory for your game
so, I'd start with looking at all of your game's functionality that involves cloning and checking for any scripting that uses looping, recursion, and/or many layers/levels/nesting of iterating (foreach-ing) arrays/lists/dictionaries
you might have to make test games for every such functionality within your game, if the issue can't be seen via looking at the scripting itself
you might also want/need to provide others who're willing and able to help with this troubleshooting with your entire game code, so they can get to work on trying to figure out the problem(s), if it is your game/game-code that is the issue...
for the cloning issue:
you could have scripting so that every time you create a clone, or any scripting creating a (non-clone) object, to count/store/display the number of clones, and/or in displaying the gotten the number of total objects, via 'ListCount (AllObjects ())', and/or n displaying the number of non-clone Objects via subtracting the total objects - the clone objects
to show you how many clones and/or total objects (objects and their clones) (and/or the number of non-clone Objects via subtracting the total objects - the clone objects) are within the game
If you're sure it's happening with clones… might be worth checking if you're destroying clones that might still be in an objectlist somewhere.
Not sure, but a quick look through the code makes me think this could potentially confuse the GC and lead to some slowdown later on.