Posts by Volnaiskra

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.

    Sounds like an intense time. If I were you, I would go to someone like a counsellor - someone who is basically paid to listen to you for an hour - so that you can debrief about the whole experience. That might give you some well-deserved stress relief.

    I think you'll be fine, but if you want peace of mind, then just create a simple stress test. Use fastloops to create a few thousand arrays and fill them up with some data, and see whether your computer explodes. If it does, buy a new computer, reduce arrays by 10% and try again.8o If it doesn't, proceed confidently with your project.

    IF there is one thing I would love to see in an upcoming release, it is a functional undo/redo, with an undo/redo action list, and with an option to jump to where the change was made

    Some specific improvements that would be nice:

    • Saving MFA doesn't wipe undo history
    • Switching editors doesn't wipe undo history
    • When you delete a group and activate group & deactivate group actions are automatically deleted, and then you undo the deletion of the group, those actions should be undeleted too.
    • Changing properties of objects (eg. rename, check visible at start, etc.) to also be undoable.
    • If you have multiple editors open, undoing affects them globally, rather than only working on the currently active editor.

    To answer your first question (why does it happen), it might help to remember that, if we think of your event as a grammatical sentence, the Active in your code is an object, not a subject.

    For example, take the sentence collars go on dogs. In this sentence, collar is the subject and dogs are the object. And most people would understand this sentence to be very clear about where collars go: they definitely go on dogs. But the sentence is not totally clear about dogs - do all dogs have collars? not necessarily, maybe some dogs do, and some dogs don't. The sentence leaves this matter rather vague.

    However, take the sentence dogs have collars. This time we've switched the subject and object. This time, the sentence is much clearer about dogs. The sentence seems to - if not state, then at least imply - that indeed all dogs do have collars. Meanwhile, this sentence seems more vague about collars. Do all collars go on dogs? Probably not...probably lots of things have collars, just like how saying dogs have eyes doesn't preclude the fact that lots of other things have eyes too.

    So, when you tell Fusion to create an "Object" at "Active", you are being clearly instructive about the subject (which, perhaps ironically, in this case is called "Object") and vague about the object (which in this case is the "Active"). So, Fusion knows that you want to create an "Object" at some "Active". Though it doesn't actually receive any strong hint from you that you want it at all Actives. Maybe you could say that it interprets your 'sentence' as Create an "Object" at an Active, or perhaps Create an "Object" at the Active. So it grabs the closest Active at hand (which is the most recently created one) and creates one there.


    Now, there is a way to reverse the subject and object. You could use the Launch Object action. You would access this from the Active's dropdown, which would make the Active, rather than the "Object" the centre of attention of this action (ie. the object).


    Please login to see this picture.


    Launching objects is usually for bullets and things, but if you launch it at a speed of 0, then it'll be unmoving, if that's what you want. What's interesting is that if you have a speed above 0, then the object will move, even if it doesn't have any "Movement" (eg. bouncing ball) assigned to it. (I assume it automatically turns it into a bouncing ball object?). Anyway, as you can see below, it creates the object at all instances.

    If this approach doesn't work for you, then I would use a forEach loop, as semar suggested.


    Please login to see this picture.

    Does your code include wall collsion code? In other words, what would happen in the below situation - where there is a wall blocking the player's horizontal movement - would the player stop, or would he walk through the wall?


    Please login to see this picture.


    Because it looks to me (albeit without seeing your code) like you have events that block vertical movement if the player hits an obstacle during Y movement, but possibly not events that block horizontal movement during X movement. The problem in your GIF seems to be about the latter. Though it's natural to think of your platforms as floors, in the case of your GIF the platform acts more like a wall, because the player is bumping against the side of it.

    It sounds like you've refined your enemy AI to such a degree that it's almost like the Tyranid Hive Mind (and I'm sure you get the reference), a singular entity doing all the enemy thinking as one, then distributing it around them as appropriate for their environment and the players actions?

    It's a great idea, but a long way off for a guy at my level. I imagine that the knowledge and understanding to create such a thing takes thousands upon thousands of hours of experience, trial and error across many projects before you finally 'get it', but that's where I want to be one day as it sounds like it has huge potential and all manner of gaming applications :/

    Actually, I think (I'm not sure) that my enemy system might be an example of your finite state machine: a singular but multifaceted chunk of code where all the bits are switched on or off as needed, according to the current states of the entity.

    The silver lining is that while it will be a tedious nightmare to redo all that work, you will almost certainly do a better job the second time round, and the project will be better for it.

    But still, use a cloud backup system, like OneDrive, which comes free with Windows.

    On top of that, I highly recommend a program called "OO AutoBackup", which you can set up to silently backup certain key files at regular intervals. I have mine set to do it twice daily, plus into a different location weekly, and a third location quarterly. It means that if something goes wrong with a file, I'll only ever lose a few hours of work max. But if I accidentally broke something 3 weeks ago and only realised today, I also have a much older version available that can help me recover whatever I broke.

    I think lots of variables is usually a good thing. Unless, I suppose, you keep forgetting about them and doubling up with new ones until you have 5 altVals doing the work of 1. But as long as you're well organised, giving everything its own well-named altVal is helpful, in my opinion. Otherwise you run the risk of using the same altVals for too many things at once, so that if you tweak something over here it breaks something over there. Or you get into the habit of using lots of hard-coded, unlabelled numbers everywhere, which will make your code less readable and harder to manage.

    Each of my enemy objects actually uses about 300+ variables: basically the full 260 altVals, plus all 32 flags, plus a few dozen more altVals in child objects such as skins and turrets. Every enemy in my game uses an instance of the same object, no matter the type of enemy - stationary, moving, a flyer, a shooter, etc. To create a new enemy type, all I need to do is tweak some altVals like this:


    Please login to see this picture.


    The rest will take care of itself. If the enemy moves, it will automatically navigate terrain, either flying through the air or walking on floors, walls and/or ceilings, avoiding hazards. It will jump over gaps, with a suitable air-time and jump parabola that takes into account its speed and the width of the gap, and environmental factors such as wind speed.

    If it's aggressive, it will automatically seek out the player, and eventually give up if it can't reach her. It can handle all sorts of shooting behaviour (aiming, multi-pellet bursts, heat-seeking, friendly fire) depending what I set.

    All of its animations and sounds will be managed automatically - all I need to do is provide the graphics/sound assets and put them in pre-determined spots in my game's data folder.

    The whole code is comprised of some 2000 events, but code will be automatically enabled/disabled for each instance, as needed, depending on what the capabilities and requirements of that particular enemy are. Performance is good because the system automatically optimises itself as needed (eg. slow-moving enemies won't check for obstacles as frequently as fast-moving ones)

    My enemy system is one of the things I'm most proud of. Even though I built it a few years ago and have long forgotten exactly how it works under the hood, I can create a new enemy type today, and it works 'out of the box' with little fuss. If needed, I can make small tweaks to some small portion of the system without affecting anything else.

    One of the reasons it works this well is because just about everything is contained in a single active object, with all of its various features neatly segregated amongst its many altVals. I'll go as far as to say that I simply wouldn't have been able to pull this off without 2.5+. With only 26 altVals per object, I think things would have become too fragmented and cumbersome for me to be able to mentally keep up with all the different moving parts.

    The code is too embedded in my game to easily separate out into an example MFA. But I can describe it a little more.

    Yes, fogRotationSpeed is an altVal, as many of the other ones are. There are 3 altVals that will determine rotation:


    Please login to see this picture.


    rotationRhythm is a randomly generated number between 60-68. This will be used to pick a rhythm from my rhythms Active object, because the 60th to the 68th altVals of that object have the following code (executed every tick):


    Please login to see this picture.


    The above altVals will continually generate numbers that gently undulate between 0 and 1. They'll all gently undulate at slightly different intervals, to provide some variation. They do that by applying sin() to the timer (⏱milliseconds is an altVal I use that is more or less the same as Fusion's timer). The one called moderateVariation6 is a bit different: it will have a 'plateau' effect because it will pause at 1 for a period of time each cycle. The one called stationary will not undulate at all, of course - it will always remain at 0.85.

    So every piece of fog is assigned one of these 8 random rhythms, which is stored in rotationRhythm. This is then used in the following event:


    Please login to see this picture.


    So the AltValN("~"), rotationRhythm("~") will just be one of those 8 rhythms from above which, if you recall, is a slowly undulating number between 0-1 (except when it's a stationary 0.85). On its own, this would cause each fog piece to gently swivel 1°, which is not much. So this rotation is multiplied by fogRotationSpeed (which is randomly assigned to 25-40 above...and which I probably should have called fogRotationStrength actually).

    So each fog piece will start at a random angle (determined by fogRotationStartPosition) and slowly swivel back and forth from that angle by some amount between 25°-40°.

    I do a similar thing with the scale:


    Please login to see this picture.

    I do similar things in my notes, anything referring to an upward movement/top colliders/jumping and hitting a ceiling etc being sky blue, downward stuff being brown like earth....

    I hear ya ^^

    Please login to see this picture.



    By the way, I would encourage you to get Fusion 2.5+ (I don't see the icon for it under your avatar), as creating a well-organised MFA is harder without it. Global events can be a great time-saver, but I found them barely usable without the DLC. For me, the DLC's Find all feature is an indispensable upgrade to the old Find feature. Having 260 instead of 26 altVals means you don't have to split them into multiple objects then waste time rummaging through them to find the right altVals. Qualifiers are a great way to streamline and organise your code, and you can integrate them into your project more tightly and clearly once you have the DLC and can give them custom icons and names.


    8| Awesome

    how did you make that panel? :/

    It's mostly comprised of lots of counters/strings all lined up. The framework to set it all up comes as part of Please login to see this link.

    Thanks for all the advice folks, I've actually clocked over 3000 hours practice in Fusion over the last few years (yes I log it) so there's a fair bit I can do now, but I'm getting to the stage where I'm trying to tie it altogether into a properly thought out and structured approach rather than just hot shotting ideas when they come to me.

    I'm feeling like effective coding doesn't come down to being able to do loads of fancy clever tricks, but rather how good you are at pulling together the basics in a consistent, disciplined, logical fashion?

    OK, well, you've had plenty of experience, so my comments about 'getting your feet wet' clearly don't apply. I totally agree with you about the importance of a disciplined and thoughtful approach.

    For what it's worth, I can give you a peek at how I've done things in my game. I don't know if it qualifies as a state machine (probably not, or at least not entirely) and I don't know if it would meet the approval of any programming theorist. I never studied programming in any proper way, and I'm basically self-taught. Which means I made the dubious choice to pick a teacher who literally didn't know what they were doing.

    But Steam says I've spent over 19,000 hours in Fusion, and 95% of that has been on Spryke. In that time, I've (eventually) done a good job of making an engine that works effectively and is easy for me to understand. In the first couple of years I was more haphazard, and by about year 3 I'd ended up with spaghetti code, a mountain of bugs, and had to redo a lot from scratch. Since then, I've been very disciplined with keeping things modular and well-organised. I'm pleased to say that even if I revisit pieces of the engine I made 5 years ago, I'll generally still find my way around pretty comfortably.

    I can't overstate how important I believe it is to keep everything about your MFA organised and clear. Not just the code, but the frame editor, the icons, the naming conventions, the general workflow, and of course you should comment extensively. If you allow yourself bachelor habits, what starts as a few dirty socks in the corner today will eventually become a labyrinth of lost belongings and mysterious smells. It's the same with an MFA.

    I keep my variables organised in relevant objects, and I give those objects 50x50px icons that are easy to read in both the Frame Editor and the Event List Editor. For example, this is my Spryke States object:

    Please login to see this picture.


    Inside it are all the different state-related variables of the player character. I use a clock icon to differentiate those that are timer-based variables, and a flag icon for flags, so that I immediately know what I'm dealing with when I see it in an expression. I group them logically and use other altVals as dividers and headings:

    Please login to see this picture.


    I can keep track of many of these variables during runtime in my debugging panel (the blue section):


    Please login to see this picture.


    In my code, I first set a bunch of parameters for the physics of the movement engine. For example, gravity. The gravity changes depending on various factors in the game. When Spryke jumps normally, it's one value, when she jumps on a special trampoline platform, it momentarily becomes weaker. While she floats in a bubble, it becomes weaker still...and so on. I set all these different gravity values early on, in my "config" section:


    Please login to see this picture.


    Lower down in my code is a group called Spryke States where all the various things that can determine or affect the player's state are processed:


    Please login to see this picture.


    For example, if the player is not on the ground, and is moving downwards, then I determine that the player is falling, which will activate the IF: falling = 1 group (this group is continually closed earlier in the code, so it will only run if it's turned on here, because falling=1):


    Please login to see this picture.


    In this group, I set up various things that need to be set up. For example, I cancel out certain states/variables that clearly don't apply any more (eg. set jumping and isStopped to 0). Some things will be set no matter what (event #5654), while others must only be set if the player is not on a wall (event #5648). I also set the gravity (how much the player will be pulled downwards per frame) and the fallCap (how fast the player is allowed to drop before further acceleration is stopped):


    Please login to see this picture.


    However, some of the things that were set here may yet be overridden. For example, lower down is the Floating section of the code. And if in this section the player has been determined to be floating, then a bunch of different code will execute. Including different gravity and fallCap values that will overide what was set earlier:


    Please login to see this picture.


    Once all of the player's internal states have been processed, we then process various mechanics that can affect the player externally:

    Please login to see this picture.


    For example, if the player is standing on a vertical platform, we make a note of it in the Spryke States object by setting vertFloater to 1, and we record how fast that platform is moving in YmovingPlatMovement:


    Please login to see this picture.


    Notice that the player object hasn't actually been moved in any way yet. There have been no set X(player) to... or set Y(player) to... actions thus far. All I've done is set a bunch of variables. Once the entire Spryke States and Movement-related Mechanics groups play out, the variables will have been set, cancelled out, and overidden as needed, and we arrive at the final states that the player is in. Only then is it time to actually process the movement:


    Please login to see this picture.


    So, for example, we now apply the gravity (insofar as the fallCap will allow). As we saw above, what those values actually are will depend on various factors. But by the time we get to this point, it's all been worked out, and they are what they need to be, depending on the various player states:


    Please login to see this picture.


    After applying gravity to the Y speed, we then adjust it for various other things that may be affecting Spryke. For example, the vertical platform platform we registered earlier. Notice that YmovingPlatMovement will actually be added to Spryke's Y movement every single frame, no matter what. Most of the time, YmovingPlatMovement will be 0 so won't have any effect. But whenever the player is indeed on a vertical platform, YmovingPlatMovement will be set appropriately above, and will be applied here.


    Please login to see this picture.


    We then consolidate everything into a final value yMovePixelPerFrame (second-from-bottom action in above pic) that will be used to actually move the player:


    Please login to see this picture.


    Finally, once the movement has been completed, we reset a bunch of stuff, and perform a battery of tests to see where the player has now ended up (eg. is she now touching a wall? if so, what type of wall?), some of which are shown below.


    Please login to see this picture.


    Spryke has been moved, and the code is totally up to date with her various states. Now, and only now, we ensure the appropriate animation is playing, depending on her various states:


    Please login to see this picture.


    So that's, broadly speaking, the process. Everything happens in due course, in an appropriate part of the code. All the different physics and movement parameters are stored at the top, where I can easily see and modify them. They will then be applied as appropriate by subsequent groups. First we determine the player's various states, then we check whether she's being affected by any external mechanics. Only once we know all this information do we perform any movement. Finally, once we've moved the player and re-measured her relationship with the environment, we update her animation. Here's a snapshop of my Event Manager window:


    Please login to see this picture.


    You will have noticed that I use a lot of graphic characters in my group names. Keeping things clearly labelled and visually segregated helps remove cognitive friction so you can spend more mental energy problem-solving and less on trying to remember what does what. I posted a big list of useful characters Please login to see this link.. I have dedicated buttons on my streamdecks/macropads for my most commonly used ones, and I use a pop-up clipboard manager called Phrase Express for the rest:

    Please login to see this picture.

    Somebody requested an alternate way to purchase VACCiNE 2 a couple of weeks ago, since the Clickstore is down. I can't remember who it was, and the thread they posted on seems to have been since closed (I can find it on Google but get access denied when I click it).

    Anyway, hopefully they see this post. I've uploaded VACCiNE 2 on Itchio, so you can now buy it here: Please login to see this link.

    Thanks for the suggestion Semar, I get the general idea of what you're describing even if I still don't really understand it, but I'll do a test and see if it makes more sense to me that way.

    About overcomplicating things you're probably right, but I am still very new to coding. I'm a bit of a perfectionist, and perhaps handicap myself by always trying to find the best way to do something, when I should simply be looking for *a* way at this point in my journey?

    It sounds like you're a bit hazy on both (a) how exactly the logic of your state machine should work, and (b) how that logic would be practically implemented in Fusion. Given that, perhaps you should just allow yourself to spend some more time playing around in Fusion, getting your hands dirty, and with the handbrake off.


    You're absolutely right to be concerned about these sorts of good practices from the outset. Spaghetti code is the worst, and is easy to fall into unless you have a discipline and a good plan. But on the other hand, you're not going to have a truly good plan if you don't have clarity of mind about what you're building. And you won't have clarity of mind without first getting your feet wet and learning from a few of your own mistakes. Don't get so hung up on building the perfect scaffolding that you run out of energy to actually build the house.

    So you basically want to be able to generate a properly random seed, but the problem is that you've already set the game's seed to something specific, so now if you try and create a new randomised seed using Random(), it will be the same every time. Am I understanding correctly?

    If so - and assuming you only need to create this genuinely randomised seed once - then why don't you just generate a properly random number at start of frame and save it in an altVal, before you set the game's seed. Then, when it's time to use the randomised seed, just pull it from the altVal.

    Well I'll be dang. When you put it all like that, it makes a lot of sense, and cleaning up these events on my part will probably greatly increase RAM/reduce filesize and memory usage, too! Thanks, man. Just to double check, is this pretty much how it should look, going by your post?

    Please login to see this attachment.

    Yes.

    There are a few things I would nitpick, though broadly speaking, that's correct, according to the suggestions I made above. These are the things I would nitpick:

    • If I was in charge, the first things to be lined up against the wall when the revolution came would be unnamed altVals and flags. Spare a thought for poor future you having to make sense of your code, and name your flags.
    • As I mentioned, I'd prefer to see Fusion's native forEach loops, not the old 3rd-party ForEach extension. The native version is likely to be more optimised, and perhaps more reliable. Having said that, if the extension works, and it's what you're used to, it's probably not doing any harm.
    • I guess events #4 & #5 no longer belong in the group called "Loops", since they no longer are part of the fastloop.
    • If you wanted, you could combine events #4 & #5 into a single event, using an Or (logical) condition

    Considering all the above, this is how I would arrange the code:

    Please login to see this picture.



    In case you're unsure, this is how you create a native forEach loop. The action to start it is found in "count", here:


    Please login to see this picture.


    And the condition to demarcate the forEach loop's contents is found here:

    Please login to see this picture.




    There's another thing I want to point out from earlier, though it's no longer relevant to this particular code. Action #2 in the below event (Stop loop "Move") serves no purpose.

    Please login to see this picture.

    Action #1 in this event (Start loop "Move" [Velocity] times) will jump over to the fast loop called "Move", and will run it as many times as commanded (ie. whatever the integer value of Velocity is). That is, it will run all events in the entire frame that contain the condition on loop "Move" in them, as many times as necessary. Once it completes all the required loops of those fastloop events, it will come back to this event and continue on from Action #2. Action #2 tells Fusion to stop the fastloop, but by the time Fusion gets here, the fastloop has already run its full course, so is already stopped.




    Contiuning on from the changes I made from your last post, would anything need changing for this particular event, wherein bullets hit the enemies?

    Please login to see this attachment.


    Aha. Ok, now that I see this event, I realise why you were using a fastloop. I should have clicked earlier.

    So, earlier, I talked you into moving the bullets in one single go, rather than increment by increment. So if velocity   was 8, it would move them by XVel x8, instead of by XVel x1...XVel x1...XVel x1...XVel x1...XVel x1...XVel x1...XVel x1...XVel x1. However, what I didn't see (but should have guessed) was that you were checking for collisions during this loop. Because your bullets are so fast, if you move a bullet the full Xvel x8, it might skip over an enemy entirely before you have a chance to do a collision check. Which is why you were doing a collision check every XVel x1 increment, to make sure that you caught any collisions that occurred in the middle of the bullet's journey, and not just those at the end.

    So, my advice to get rid of the fastloop was actually bad advice. You probably do   need to check in XVel x1 increments. However, the same problem that I identified in your events #5 & #6 (where you were performing 1152 checks per frame) is also present in this event #1329. And because overlap checks are relatively expensive, it's likely to have an even greater affect on your lag.

    Because you didn't add a Fixed Value of Group.Bullet = LoopFV, "Move" condition to event #1329, it was continually checking whether any bullet had collided with an enemy, instead of just whether the currently fired bullet had collided. So, when the code performed the "move" fastloop for bullet 1, it would check whether bullets 1-12 collided with an enemy. If it ran the fastloop 8 times, it would perform those 12 checks 8 times. And then it would move onto bullet 2 and repeat the whole process again, and then 10 more times for the remaining 12 bullets. So it'd be checking for overlaps 12*8*12 = 1152 times per frame. What you want is for it to check for overlaps 12*8 = 96 times (8 increments for each of the 12 bullets). Still a lot, but much less than 1152.


    Here's the crux of the issue: forEach loops scope, while fastloops do not. So, when you do this:


    Please login to see this picture.

    Event #3 inherits scope from event #2 (it will only affect bullets with Flag 1 off). But when it jumps off into the "Move" fastloop, the scoping is abandoned. When Fusion gets to this point:

    Please login to see this picture.

    ...there's absolutely no scoping any more. It's a clean slate.

    Luckily, you re-introduce scoping with this condition, which seems to be a mechanism that your ForEach extension uses for this purpose:

    Please login to see this picture.

    So these actions will only affect the scoped bullet:

    Please login to see this picture.

    But then the fastloop moves onto here, and again there is no more scoping, and it's a clean slate. So when you ask Fusion to check whether a bullet is overlapping an enemy, it has to check all the bullets:

    Please login to see this picture.


    So, here is how I would do the code, amending my above changes to reintroduce the fastloop. When Fusion's native forEach loops are combined with fastloops as below (with the fastloop being the topmost action - the forEach condition will no longer be green), the fastloop will keep the scoping of the forEach loop. I've called the fastloop "MoveByIncrement" so that it has a different name to the forEach loop, to avoid confusion.


    Please login to see this picture.


    Notice that I've changed the order of these two conditions in event #5, compared to how you had them:

    Please login to see this picture.

    That's because overlap checks are relatively expensive, so you want to minimise them where possible. If Velocity=8 and an enemy's HP is 1, and a bullet hits and kills that enemy in the very first loop of the fastloop, you don't need the code to check for that enemy's overlap and its HP seven more times. You also don't need the 11 other bullets from the same shotgun spread to keep triggering their own overlap checks for this enemy. Better that the event checks HP first, so it can avoid checking overlaps whenever an enemy is already dead.

    The previous order would check for overlap on all enemies, and then check HP only for some enemies (ie. collided enemies). This order will check the HP of all enemies, and then check for overlap for most enemies (ie. alive enemies). The trade-off is that you'll be doing more HP checks, but potentially fewer overlap checks. Since HP checks are considerably cheaper, this should be a worthwhile trade-off.


    Let me know how that goes.

    I watched the video, but once the syntax got rolling it was all just goobledygook to me. My distate for syntax-heavy programming is why I use Fusion. But from what I could make out of the general gist of it, the concept seemed fairly simple, and I assume that I probably follow some of the state machine principles in my own work, without particularly thinking about it, or explicitly referring to them as state machines.

    If you can describe a simple example of a specific state machine, in plain English, then perhaps one of us can explain to you how you'd build that in Fusion.

    In the fast loop, put all the set commands in a child event. This way, they will performed after the creation of the bullet.

    Are you talking about the event below? Because if so, then that's not the case.

    As it is now, the actions will be performed after the creation of the bullet, and will affect only the newly created bullet. Which is surely what Please login to see this link. wants.

    If those actions were put in a child event, it would actually break the code. Fusion currently has a limitation where child events do not inherit scope of objects that were created in a parent event (they inherit scope of objects that were scoped    by the parent event's conditions, but not objects that were created    in the parent event's actions) . So those actions would be applied to all bullets everywhere, which would break the game.


    Please login to see this picture.



    Yes Volnaiskra you are right, however Please login to see this link. creates 12 objects in one event, and at the end changes some property of that object, may be without knowing that the changes affect only the latest created one, because of object scoping.

    I just wanted to point it out.

    But you were talking about a fastloop, where only 1 object is created at a time, not 12 at a time. And you said that in such a case using a qualifier would affect all objects instead of just the newly created object, which is incorrect. Using a qualifier after creating an object is fine; if the created object uses that qualifier, then only that object will be affected.

    Please login to see this picture.

    There are a few problems here.

    First off, you're using some old ForEach extension from 2010. I guess this is what people had to use before Fusion introduced native ForEach loops in 2013 or so. You should probably use the native forEach loops. I'm sure they'll be less laggy for a start.



    The way you combine the forEach loop and fastloop in events #3 & #4 seems odd, and is surely contributing to your lag. It looks like you're creating complication and busywork for Fusion without any benefit. Do this:

    • Get rid of both actions in event #3
    • Move the 4 actions in event #4 to event #3
    • amend the top 2 actions to:
      • Set Xpos to Xpos + XVel *Velocity
      • Set Ypos to Ypos + YVel *Velocity
    • remove the fastloop-related conditions and actions in events #5 and #6
    • delete event #4


    Let's say your bullet's velocity is 8. This is what's happening at the moment, for each bullet:

    • Start a loop 8 times
      • Loop 1: check every bullet in the game to find the one with the right fixed value
      • Loop 1: Move the bullet by XVel x1 and YVel x1
      • Loop2: check every bullet in the game to find the one with the right fixed value
      • Loop 2: Move the bullet by XVel x1 and YVel x1
      • Loop 3: check every bullet in the game to find the one with the right fixed value
      • Loop 3: Move the bullet by XVel x1 and YVel x1
      • Loop 4: check every bullet in the game to find the one with the right fixed value
      • Loop 4: Move the bullet by XVel x1 and YVel x1
      • Loop 5: check every bullet in the game to find the one with the right fixed value
      • Loop 5: Move the bullet by XVel x1 and YVel x1
      • Loop 6: check every bullet in the game to find the one with the right fixed value
      • Loop 6: Move the bullet by XVel x1 and YVel x1
      • Loop7: check every bullet in the game to find the one with the right fixed value
      • Loop 7: Move the bullet by XVel x1 and YVel x1
      • Loop 8: check every bullet in the game to find the one with the right fixed value
      • Loop 8: Move the bullet by XVel x1 and YVel x1

    The end result will be that the bullet will move by XVel x8 and YVel x8, but we made Fusion do a lot of work to get there.


    If you follow my suggestions from above, this is what will happen, for each bullet:

    • Move the bullet by XVel x8 and XVel x8

    The end result will also be that the bullet will move by XVel x8 and YVel x8, but with far fewer steps, which will create less lag.



    A further problem you have is that you've put events #5 & #6 inside the fastloop. This caused those events to run far more often than they need to. If you had 12 bullets, each moving at Velocity=8 then you were forcing poor Fusion to perform those 2 checks 96 times every frame, when once per frame is enough!

    Actually, it's worse than that. You didn't have the Fixed Value of bullet = LoopDV, "Move" condition in events #5 & 6, so those checks weren't even scoped. So, it would check every single bullet every single iteration of the fastloop. Let's say you have 12 bullets, with a Velocity of 8. This is what would happen:

    • MOVE BULLET 1
      • Run "Move" fastloop 8 times
        • Fastloop 1: Move Bullet 1
          • Check if Bullet 1 is out of bounds
          • Check if Bullet 2 is out of bounds
          • Check if Bullet 3 is out of bounds
          • Check if Bullet 4 is out of bounds
          • Check if Bullet 5 is out of bounds
          • Check if Bullet 6 is out of bounds
          • Check if Bullet 7 is out of bounds
          • Check if Bullet 8 is out of bounds
          • Check if Bullet 9 is out of bounds
          • Check if Bullet 10 is out of bounds
          • Check if Bullet 11 is out of bounds
          • Check if Bullet 12 is out of bounds
        • Fastloop 2 : Move Bullet 1
          • Check if Bullet 1 is out of bounds
          • Check if Bullet 2 is out of bounds
          • Check if Bullet 3 is out of bounds
          • Check if Bullet 4 is out of bounds
          • Check if Bullet 5 is out of bounds
          • Check if Bullet 6 is out of bounds
          • Check if Bullet 7 is out of bounds
          • Check if Bullet 8 is out of bounds
          • Check if Bullet 9 is out of bounds
          • Check if Bullet 10 is out of bounds
          • Check if Bullet 11 is out of bounds
          • Check if Bullet 12 is out of bounds
        • Fastloop 3 Move Bullet 1
          • Check if Bullet 1 is out of bounds
          • Check if Bullet 2 is out of bounds
          • Check if Bullet 3 is out of bounds
          • Check if Bullet 4 is out of bounds
          • Check if Bullet 5 is out of bounds
          • Check if Bullet 6 is out of bounds
          • Check if Bullet 7 is out of bounds
          • Check if Bullet 8 is out of bounds
          • Check if Bullet 9 is out of bounds
          • Check if Bullet 10 is out of bounds
          • Check if Bullet 11 is out of bounds
          • Check if Bullet 12 is out of bounds
        • Fastloop 4: Move Bullet 1
          • Check if Bullet 1 is out of bounds
          • Check if Bullet 2 is out of bounds
          • Check if Bullet 3 is out of bounds
          • Check if Bullet 4 is out of bounds
          • Check if Bullet 5 is out of bounds
          • Check if Bullet 6 is out of bounds
          • Check if Bullet 7 is out of bounds
          • Check if Bullet 8 is out of bounds
          • ..........

    .......and so on. I didn't even get halfway through the very first bullet. If my maths is right, you were forcing Fusion to perform those out-of-bounds checks 1152 times per frame. (Actually 2304, since you have two separate out of bounds checks). When really, all you need is 12 checks per frame - 1 for each bullet. Which is what will happen if you make my suggested changes from above.


    I hope that helps.

    Thanks for all help so far. However, it seems as though whichever method I use, something goes wrong. With ForEach, obviously there's the issue of the ForEach loops lagging. With one other method I tried (running fastloops on each individual pellet), that had issues with hit registration for some reason (IE, many pellets just wouldn't connect even when they should) The method you guys have shown me so far seems to work the most reliably, BUT, when several pellets connect at the same time, CF2.5 only seems to scope one of them, demonstrated here: (For context, that counter is supposed to be a playtesting way of gauging when a pellet hits, and does 17 damage, and since there are 12 pellets, that counter should hit 204 when the pellets hit that building)

    Please login to see this link.


    Please login to see this attachment.Please login to see this attachment.

    I can see screenshots of your creation code, but not your collision code. If you post a screenshot of your collision code, perhaps we'll be able to tell what's preventing all bullets to scope properly when multiple bullets hit something at the same time.