Scoping "hitbox" objects?

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.
  • So, I have a game level in progress, in which enemies spawn, and so do invisible "hitbox" objects, that are intended to set onto the enemies' heads and register headshots for extra damage.

    The enemies spawn fine, but so far, I've had trouble getting the hitbox objects to stick on the enemies' heads or scoping the individual enemy/hitboxes. So far, I have tried experimenting with alterable values, overlap events, Fixed values and Instance values alike, but so far, what should ideally look like this: (This is in the frame editor)

    Please login to see this attachment.

    Ends up looking like this on runtime:

    Please login to see this attachment.

    What I did notice, is that the hitboxes seemed to position themselves fine, until the first enemy is killed, at which point, they all suddenly seem to go off on their own tangents...For clarity, here are the events:

    Please login to see this picture.
    Please login to see this picture.
    Please login to see this picture.

    It may also be possible, that because I'm using the Qualifiers for these particular events, and I should probably do them on an individual object basis; but either way, any input or help would be appreciated, thanks!

  • In addition, I would bind the hitboxes to the sprite using the "Fixed Value" of the sprite.

    Each hitbox should have for example an alt. value, say, ID-Sprite, which shoud be set to the Fixed Value of the sprite.

    This way you can use this unique binding to select and/or move the hitboxes which belong to a sprite.

  • Thanks for the example, willy/semar. I shall definitely check it out.

    In the meantime, I was able to solve the issue another way - by using an active object with an "id_generator" Alt. Value, which the enemy objects and hitbox objects alike would bind their specific values to upon creation, allowing them to share the value upon spawning. (And the id_generator in question RNGs every second, whilst adding 1 to the value whenever an enemy spawns)

    However, I do still have one relatively more minor issue I need to iron out.

    Since the gunplay in the game uses fastloops to allow the guns to aim in all 360 directions (instead of the standard dismal 32) and have "realistic" bullet speed (IE MUCH faster than the default max speed of 250). This normally works like a dream, however, whenever shotguns appear, since they fire a bunch of pellets at the same time, this causes the application to lag and can mess with certain events. Is there a way to combat this?

  • A couple of things:

    1. event 5 and 6 are similar, you may need only one ( the n. 5 ).

    2. you run a fast loop (velocity of bullet) times. Inside the fast loop, however, you move the bullet adding xvel and yvel. Shouldn' t the bullet move 1 pixel only, since the loop runs (velocity of bullet) times ?

    3. if you have to move lots of bullets, try to move only one at a time, that is, don't use a for each loop. Pick a bullet (with a flag "moved" to false) at random, move it with the fast loop, and set that flag to true when finished.

    New crated bullets must have obviously the flag "moved" = false.

    4. the command "stop loop" in the event n.3 should be a child event. This way it will be executed after the fast loop - very important !

  • 1. The second one deletes bullets that are off-screen, otherwise the loop can induce lag when the bullets are "at long range" so to speak.

    2. It might not be clear from the event list, but those XVel/YVel are used to calculate the angles, since the guns can be aimed in all 360 directions.

    3. I do, normally. It's just when shotguns are featured, since they shoot multiple pellets at the same time. But yeah, I'll try this for the pellets exclusively (since I can just remove the Group.Bullets qualifier and give them their own set of events)

    4. Noted, thanks.


    Here's what a shotgun event looks like in the editor:

    Please login to see this attachment.

    (Each shotgun shot features 12 pellets)

  • Bare in mind the object scope !

    When you set the angle, xvel, yvel of a bullet, only the last created bullet will be considered - this is the object scope.

    You may use a fast loop here, run it 12 times, and inside the loop create a bullet and set the angle and x,y speed accordingly. Do not use the bullets qualifier in this case, instead use the bullet object, otherwise you set angle and speed to all your bullet objects at once !

  • You may use a fast loop here, run it 12 times, and inside the loop create a bullet and set the angle and x,y speed accordingly. Do not use the bullets qualifier in this case, instead use the bullet object, otherwise you set angle and speed to all your bullet objects at once !

    Using a qualifier would probably be ok. If you create an object and then perform an action on one of its qualifiers in the same event, Fusion will automatically scope the qualifier to the newly created object. I use this technique all the time. It can actually be super useful when combined with Create by name.


    Please login to see this picture.


    The bottom 4 actions in the above screenshot refer to a qualifier. I have lots of objects with that qualifier, but they will only affect the object that is created in the 1st action.

    In fact, this is the only way I know how to perform any actions on the newly created object, since I don't even know that that object is! All I know is that the object will be called "P...." with various numbers at the end. I can't use a regular Active Object in those actions, because not only do I not know which object will be created, none of my "Pxxx" objects even exist in the frame! (they are in an "included frame" so will be accessible to the runtime, but are not accessible to this frame at edit-time while I'm writing the event). But none of this is a problem, because Fusion lets me scope this mystery not-yet-existing object with a qualifier. :)

    Please login to see this link.
    My Fusion Tools: Please login to see this link. | Please login to see this link. | Please login to see this link.

  • 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.

  • 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.

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

    Hmm.. these are not 12 bullets/pellets, they seems to be a bit more. Why ?

    Oh, that - I was playtesting two separate versions of the event. Since the event is for a double-barreled shotgun, which has an altfire mode allowing it to fire two shells (24 pellets) at once (at the cost of much worse accuracy) :3

    Thanks again, I'll set child events...wait, is there an alternative method? Only reason I ask is that I currently only have the vanilla version of CF2.5 and can't afford to throw money at the 2.5+ Addon at the moment. If not...guess I can wait a couple weeks.

    Is there any specific event that should be used for the Child Event?

  • 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.

    Please login to see this link.
    My Fusion Tools: Please login to see this link. | Please login to see this link. | Please login to see this link.

  • 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 link.
    My Fusion Tools: Please login to see this link. | Please login to see this link. | Please login to see this link.

  • 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.

  • 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.

  • 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.

    Please login to see this link.
    My Fusion Tools: Please login to see this link. | Please login to see this link. | Please login to see this link.

  • Right, right! Now it's all coming together, thanks! Speaking of, before I showed you the collision/overlap events, I did try the prior version and seriously wondered why the bullets weren't registering hits half the time. :S

    For context, I've tuned the events to pretty much exactly how you've suggested, and now here are what the shooting/colliding events look like:

    Please login to see this attachment.

    Please login to see this attachment.

    (Excuse the event cutting off. It's pretty much the same event, but for when the bullet is overlapping the "Group.Targets", which are headshot hitboxes, causing the bullet to do more damage)

Participate now!

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