Fastloops causing slowdowns. Workaround?

Welcome to our brand new Clickteam Community Hub! We hope you will enjoy using the new features, which we will be further expanding in the coming months.

A few features including Passport are unavailable initially whilst we monitor stability of the new platform, we hope to bring these online very soon. Small issues will crop up following the import from our old system, including some message formatting, translation accuracy and other things.

Thank you for your patience whilst we've worked on this and we look forward to more exciting community developments soon!

Clickteam.
  • 'Ello again, all.

    I'm experiencing quite a bit of slowdown in a project of mine with what I think primarily involves the AI code and Fastloops in an RTS-style game running at 50 FPS. After about fifteen or so enemies on screen/ in the frame at once, the game starts slowing down, and if there's too many enemies, it downright crawls. What I'm looking for is advice on how to optimize my code better to try to prevent possible unnecessary Fastloops. Running it in HWA/ Direct 3D9 speeds it up a tiny bit for me, but I want the game to be able to run with unnoticeable performance issues even on the Standard display mode.

    I'm wondering if there's a way to select individual objects and the objects they're grouped with (like shadows or detectors or bullets) without using Fastloops, and also while keeping MMF2 from picking every instance of the object and having it act like only one of them. A lot of the AI uses distance floaters grabbed from the Advanced Direction Object and stores them as Alterable values as well, so a lot of objects have individual values for how far away something is from them, then constantly search to grab those Fixed values from them. Is there another, less resource-dependant way to do this?

    It makes me wonder how larger 2D RTS games, like Starcraft, can handle so many units. But then, Starcraft also runs at 24 FPS normally...

  • Never heard of the ForEach object before... or "action loops" either. Maybe my comp is on the slow side, as I only get 650ish fps when I run that. Are there any tricks to using that when it comes to a lot of different enemy types with AI and shooting projectiles and the like?

    What I've done is, on the creation of an object, it'd have an internal Flag 0 set to "OFF". Then on another line, where a condition would look for that flag, it'd set it to "ON" while also creating its paired objects and within those paired object, an Alterable Value would be set to the Fixed value of the first object. It helped really well to keep things together, even when it came to that object and its pairs being destroyed in various ways, but seemed to need a fastloop to work.

  • LB's example is great for object pairing but if you want to check the distance of each active against every other one (as you would need to for RTS style AI) you would usually need to run a loop that stores the distance from the selected active in an alt of all the other actives, then pick the closest one to do actions on.

    There's an example of this here: Please login to see this link.

    Or alternatively you could check out my example - using a slightly different system - if you want to reach > 500 units: Please login to see this link.

    Good luck!

    Please login to see this link. | Please login to see this link. | Please login to see this link. | Please login to see this link.

  • Oh, I know. I've gotten that to work, and really, my own code works just fine! ... Except for the slowdown when it comes to only a handful of objects (units?) being on screen or just anywhere on the frame at once, and even if they're just sitting there, which is definitely a consequence of fastloops. It gets worse once they start firing (more objects, and even some of those are looped, depending on how they behave as a projectile), but I've a sad feeling I may have to recode the entire AI from scratch. I'm about to go to bed though, so I'll have to check the example tomorrow! :)

  • LB is my hero as always. =]

    Are ForEach loops always faster than Fastloops?

    I've replaced all fastloops for every enemy object I have in my game, and slowdown has been considerably reduced! Although some still exists, primarily when enemies decided they all want to target and shoot something simultaneously, and as such, slowdown has to do with object spam at such points; but I have a few things like the player and player weapons still on fastloops. I thought that they'd not be too bad since most of the time there's only a few projectiles being fired, but if ForEach loops or Action Loops are still faster. The weapons themselves I've noticed hadn't seemed to have contributed to the slowdown before, but still in some situations, the framerate drops below 50.

    And also, to reduce objects, would something like raycasting be faster to process as opposed to separate projectile objects? (I have three objects per bullet, usually). If I knew how to make a bullet instantly appear where an enemy is aiming and also hit obstacles if missing, I'd put that in.

  • Kid_Roleplay - you might find Chris Burrows tutorials useful: here's one for fast bullets you might be able to adapt: Please login to see this link.
    It uses fast loops, but you might be able to adapt it to use ForEach. He also has some other good examples and tutorials that might help.
    Good luck!

    Kevin Ayre Please login to see this link.
    My iOS Apps: Please login to see this link., Please login to see this link. and Please login to see this link.

  • x.x I've got soldier units who all fire multiple bullets, three times per burst. Each burst, they create an invisible detector object for the traveling bullet, an invisible detector at the destination the bullet will go (not necessary for some weapons), the bullet that the player sees which is assigned an angle during that burst, and a glowing overlay. Twelve objects. When you have a lot of soldiers firing, that quickly gets overboard, and though my machine can handle a bunch of them already, it still causes slowdown, yet I'm looking to have even more enemies than should probably be, since they're a really disposable enemy.

    What I'm wanting to do is replace the current projectiles with an invisible bullet system to reduce objects, processing (defining angles of the sprites and the paths at the instant of firing, and multiple times), and also some sort of illusion of firing three times and instead only firing once--I'd just make a three burst sound effect or something. A raycasting idea came to mind to help with obstacles it may hit as well as maximum firing distances. I'm wanting the shots to be instant and appearing on the target but not undodgeable. That kind o' thing. ^^;

    But all of this only if some kind of raycasting thing would be the way to go about it. For all I know, that might slowdown the comp even more if ten to twenty units are sending them all at once.

  • 1. you don't need to create a separate detector object for collision. put it in the bullet object's animation using the animation swap trick.

    2. what is the detector at the bullet target for? I have a feeling you don't need that either

    That would drop your object count down significantly.

    edit: 3. if the bullets are supposed to be instant, why do you need a graphic or glowing overlay for them? I might be slightly confused on that one

    Please login to see this link.

    My examples:
    Please login to see this link.
    Please login to see this link.
    Please login to see this link.

  • 1) What's the animation swap trick? o.o

    2) The detector at the target is for the maximum range of the bullet. In the case of the soldiers, it was removed, as I wanted their bullets to always travel to its maximum range, which was an alterable value used for a "life timer." When the value would count down to zero, the bullet would be destroyed. For tanks, the bullet would be destroyed if it hit that detector, which position varied depending on where the target was.

    3) The bullets aren't instant at current. I'm wanting to come up with a way to add an instant system that'll target what's being shot at but also appear to hit a wall or other obstacle further beyond it if it's inaccurate. If I replace it with an instant hitting code, then I'd have no need to draw the projectile, glowing sprites, or detectors at all.

  • 1) The animation swap trick is where you have a separate animation in your projectile which has the shape that you want to use when checking for collisions. You then do this:

    Always (or some better optimised condition)
    -- Bullet: Set animation to 'My Collision Shape'

    Bullet Overlaps Backdrop
    -- Do your collision detection stuff

    Always
    --- Bullet: Set animation back to 'Stopped' (or whatever the name of your standard animation is)

    Doing this, the player sees the Stopped animation, but the collision detections work on the My Collision Shape animation. It saves you having multiple detector objects, but the down side is that it's harder to control animations for objects like this, because the animation frame gets reset each time you change the animation. That's why it's a good routine for bullets, which usually don't get animated, but not usually a good idea for characters and enemies.


    Anyway, about bullets...

    The method I use, rightly or wrongly, works this way:
    Every bullet has an XPos, YPos, and TargetAngle in its Alterable Values. The XPos and YPos store decimal-point-accurate versions of the object's coordinates, and the TargetAngle is (obviously) the angle that the bullet is firing at. I also make a new Active to keep some values which are global to all bullets, like the distance they jump each loop (the 'Stride' value) and a value called 'Stop'. This last value is either 0 (No) or 1 (Yes). The Stop variable will tell the fastloop to stop, because all bullets have been processed.

    I use an infinite fastloop, because I'm silly. Anyway, your loop works basically like this:

    Start the Fastloop
    Some condition
    --- Start Loop 'Bullets' '-1' times (-1 makes it a scary infinite loop. While you test, put a value like 1000 here instead, so if you mess it up you're not stuck looping until Judgement Day)

    Tell MMF this will be the last fastloop
    On Bullets loop
    --- Variables: Set 'Stop' to 1

    Move those bullets using trigonometry
    On Bullets loop
    --- Bullet: Add to XPos variable:
    -------- sin( TargetAngle ) * Stride
    --- Bullet: Add to YPos variable:
    -------- cos( TargetAngle ) * Stride
    --- Bullet: Set X Position to value of XPos variable
    --- Bullet: Set Y Position to value of YPos variable

    Destroy bullets which hit a wall
    On Bullets loop
    + Bullet overlaps backdrop
    --- Make a spark or something, and a noise
    --- Bullet: Destroy

    Destroy bullets which hit an enemy
    ... Use a variation of the previous line, it should be easy to do ...

    Check if there are still some bullets left, and if there are, keep the loop going
    On Bullets Loop
    + Number of bullets is greater than zero
    --- Vars: Set Stop to 0 (Keep the loop going)

    If all bullets are gone, kill the fastloop. KaPow.
    On Bullets Loop
    + Vars: Stop == 1
    --- Stop the Bullets loop.


    That should be more or less it. I've not tested the above, so sin() and cos() may be the wrong way round, and there may be some other horrible problem with it, but it's only intended as a guide. The usage of the Stop variable to stop the loop is a little awkward, and not strictly necessary if your loop ends when all the bullets are destroyed like this one does. But I kept it there because it's handy if you need to do a loop which has survivors. MMF is easier at testing whether something IS true, rather than if something ISN'T true, so this is a way I use to get around that. In our case, you could just as easily say 'Have all bullets been destroyed? Stop loop', but where's the fun in that? :p

    Anyway, rather than using one loop per bullet, per step, this uses one loop per step, and uses ActionLoops to actually do the moving. So there's the same number of events being run if you fire 1 bullet as if you fire 1000.

    Hope that makes sense.

  • Well, it definitely looks intimidating. Also kind of scared to run an infinite fastloop with math on all bullets appearing when even 100% pure action looped bullets with vector movements causes slowdown.

    But will it work as an instant delivery kind of thing?

    Also, congrats on ONE THOUSAND posts! *Audience cheers.*

  • Dines, it's not too hard to control animation using the swap method. You just store the current frame of the animation in a variable before you change it to the collision animation, and then after you do collision stuff and set the animation back to normal, you set the frame back to whatever stored variable it was. :)

    Please login to see this link.

    My examples:
    Please login to see this link.
    Please login to see this link.
    Please login to see this link.

  • Hi Konidias :) I found there were other caveats in practice, but it may be better now, since I haven't tried using the system for anything other than bullets in years XD I think it tended to mess up animation speed too, if the maximum speed of one animation differed from the other or something, so in the end I just favoured using a detector, and keeping all the different detectors as animations in the detector object. Or something. :)

    Kid_Roleplay: The infinite fastloop only means it won't stop till you tell it to. It basically works this way: Suppose the farthest that any bullet will travel is 500px. You're making your bullets 'stride' a step of 3px on each loop. So your loop will only run 500/3 times (167 times). And as the loop progresses, more bullets are being destroyed as they hit objects, so each loop is faster than the one before it. So maybe on the first loop, you're moving all 200 bullets. But by the time you reach the final few loops, there may well only be one bullet left, so those last few loops will blast through in no time.

    But yeah, this method results in instant-hit bullets. Another way you can speed it up is when the bullet is first fired, instead of storing one 'Angle' value, you can store a 'Stride X' and 'Stride Y' value and do the sin(angle)*stride and cos(angle)*stride commands just once when the bullet is first created. Then each loop doesn't have to work out the sin() and cos() functions, it can just keep moving the bullets. This works because the bullets won't change direction in the air, so we can calculate their angles just once and then use the same value on each loop.

    If you don't like the idea of an infinite loop, you can tell your loop to run 1000 times. It doesn't matter, because the code will stop it running long before it reaches that amount.

    EDIT: OH, and one important thing :O - if you're using lots of objects, don't forget to increase the maximum object limit in the frame properties. Click the frame, and in the properties window in the 2nd tab (called Runtime Options if you mouseover it and wait for the tooltip to appear), scroll down a little and you'll see it says 'Number of Objects: 500' by default. If you're likely to have more than 500 objects, then increase this to something a lot higher. If you go over the maximum object limit, weird stuff happens.

    Edited once, last by Dines (August 22, 2012 at 11:50 AM).

  • Yup. I do have a looot of objects, but it only really gets high if something glitchy happens, like if the game randomly decides to trigger every kind of explosion at once instead of just on one target. All of a sudden, it shoots up to like 800 (there's still glitches about).

    I think it'd be better if I stick to my projectiles for now. Infinite loops or even a high repetition time per bullet still sounds frightening. I'll just have to add less soldiers on screen at once is all. It takes about fifteen of them all firing at once to slowdown the game anyway, and fifteen is way more than the player should be able to handle anyway, unless they're elite... MOST of the game's slowdown is gone, finally. :) Though there is still quite a lot of slowdown when I spawn smoke effects (basically, bullets that shoot off in a random direction but grow and shrink and alter transparency values and the like). Even putting those on action loops didn't speed things up, so it seems I've yet another dilemma!

    --- Oh, and the angle calculation was made one time only, by the way.

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!