Feature Addition: "Room Object"

0 favourites
  • Nesteris

    I had fixed this bug.

    Please re-download this plugin and download the fixed capx at this link.

    Thanks Tokinsom for sharing this capx.

  • rexrainbow

    I can see the .capx but did you upload the plugin to that link? I couldn't find it so I went to link "document of my plugins" and re-downloaded it from there.

  • Oh man, I completely forgot about that. If objects are unloaded when destroyed then we won't be having any memory issues I wonder if the manual goes into detail about that.

    rexrainbow Looking forward to testing out that .capx but I'm at work now. Will open it up as soon as I get home. Thanks for updating the plugin for all of this!

  • Where is the updated plugin? It's not in the link rexrainbow shared, I keep checking every 5 minutes but I can only see the updated .capx.

    I tried his main directory of plugins but the one I downloaded from there doesn't work properly, so where is the updated plugin?

    Really confused by that.

    Tokinsom, sent you a PM, can you check it when you get back from work please?

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Nesteris

    Link of rex_gridfreezer.

    Or download it by this tool.

  • rexrainbow


    Edit - That fixed it, thanks a lot!

  • I'm still not entirely convinced there needs to be a plugin, or even runtime features for this. There are some improvements we could make though, but I think they are just general optimisations. Several of the comments seem to be unaware of what the runtime already does. Here are some of the considerations from my runtime-engineering point of view:

    You can use existing objects, e.g. Tiled Backgrounds, to identify "zones" within a large layout. I'm not sure a new plugin needs to exist for this.

    The (relatively recent) collision cells optimisation effectively removes the size of the layout from collision performance. Since objects only check against other nearby objects, without even considering others, you can have a virtually unlimited sized layout and collision performance remains relatively constant. There will be more collision work to do if you have say moving objects or behaviors making collision checks over the entire layout at once, but it should be straightforward to use events to stop objects, skip collision events and disable behaviors for the entire layout apart from the active zone. Collision performance should not be a problem at all if you do this.

    Tilemaps are even better, since they are uniquely able to exploit the collision cells for rendering. In other words, it doesn't even consider most of the tiles in the tilemap, even if it's the size of an extremely large layout, except the tiles near the viewport. So you should be able to have a gigantic tilemap with an incredible number of individual tiles, and it will hum along just fine with no performance issues at all.

    Objects which don't animate (such as Tiled Backgrounds or Sprites with just one animation with one frame) are totally inert in the engine. If you have no events for them and don't collision check them, they take almost zero CPU time (with one tiny caveat - see below). You can also limit your own events to only deal with instances in the currently active area, ensuring you don't process anything unnecessary.

    Dynamically loading/unloading portions of a layout based on room objects.

    The question is what exactly are you hoping to load or unload here? There's talk of loading and unloading images by sections. This is only useful if you strictly keep certain types of objects to certain areas. The impression I have gotten from screenshots is that very large layouts still tend to use the same look all the way through, suggesting that you are using the same set of images all the way through, which suggests that there are rarely sets of images unique to just one particular area of the layout. So it doesn't seem that there's much to save here. Perhaps very large areas will use different "world" styles, such as "desert" world turning in to "snow" world, but surely these are large enough sections to conveniently break off in to separate layouts anyway? Has anyone actually really run in to image memory use problems here?

    Then even if we implemented this, then it will jank the game as it loads new images (e.g. a 500ms pause while it uploads the next set of textures). This ruins the smooth flow between sections, so I'd still recommend using the existing layout-by-layout loading system where an entire layout is either loaded in its entirety or not at all.

    2) Destroy all objects outside layout zone (x1,y1,x2,y2)

    As I covered above, in many cases even destroying all the objects outside the current active area will not affect performance. It won't improve collision performance nor will it save you running events on extra instances, if you've designed your events well. Also since there's a surprisingly significant amount of work in the engine when creating and destroying objects, creating and destroying large numbers of objects at once could cause jank as the next section is created. I would prefer to allow the entire layout to exist at once, but make sure the engine can handle that with good performance (assuming the game is efficiently designed as well).

    1) Re-Load layout zone (x1,y1,x2,y2)

    This is as far as I can tell so far the only unique and possibly helpful suggestion. As I understand it you simply want to take an area, and revert it to its initial state as it appears in the layout view, correct? Surely you'd want to limit this to certain types of object (e.g. not the player)? It seems a relatively straightforward suggestion, but there are still difficult edge cases. Suppose there is a ball inside that area, and during gameplay it rolls away to outside that area, and then some event creates a new ball inside the original zone. Then you re-load the layout zone. There are a few options:

    • destroy both balls and recreate a new one
    • destroy the new ball and move the original one back
    • destroy the original ball and move the new one back
    • leave both balls and create a third new one in the initial location

    I'm not sure what option is best, or if there are legimitate reasons to use more than one of these cases. I'd prefer it if it was either the first or last, since they are the simplest cases (possibly destroy everything, then create the initial setup again). This could be added though if it's helpful, although as I mentioned before creating batches of objects can jank.

    A bit of a sidetrack: I tried creating an extremely large layout (64,000, 48,000) and populating it with an extremely large number of objects (~64,000).

    This was an interesting project to profile, thanks for sharing

    1. The resultant runtime.js file, even after minification, is huge (over 6mb).


    3. The game takes a long time to start...having to generate all those objects no doubt.

    As of the latest beta this is split off in to a separate data.js file, and the executable Javascript in runtime.js remains approximately the same size. The size of data.js is not especially important. It basically just means it takes longer to download. There should be no direct impact on runtime performance if the data file happens to be large. From what I've seen the long startup time is simply from having to parse the data.js file. Again this should be faster in the latest beta (data.js is pure JSON and is parsed with a JSON parser instead of needing a full Javascript engine to run it). However there's not much that can be done to further speed it up, that data still gotta be parsed!

    2. The resultant game slows down badly ... I notice that draw calls take up a lot of the cpu

    This exposes the one performance issue with extremely large layouts using lots of Sprites (you have tens of thousands!). The draw call overhead is expensive because collision cells don't apply to rendering objects: every tick it has to check if it needs to draw every instance in the layout, and you have 64,000 objects, so it has to check all of them every tick! The drawing algorithm currently looks a bit like this:

    For each layer:

    For each instance on this layer: (you have 64000 sprites here)

    • skip if invisible
    • skip if width or height is 0
    • check if bounding box changed (if so, update it)
    • skip if its bounding box is entirely outside the viewport
    • draw it

    So currently for 64000 sprites it does:

    • check if visible: yes
    • check if width or height is 0: no
    • check if bounding box has changed: no (the objects never move)
    • check if it's bounding box is entirely outside the viewport: here most of the 64000 are discarded. Ultimately only those visible on-screen get draw calls made for them.

    These steps are very simple and fast, and normally don't use any significant CPU time at all. But since you've shoved 64000 sprites in to a single layer, each and every step becomes expensive. So you can optimise it: make it skip sooner!

    Notice the very first check is "skip if invisible". I made an event where if you press a keyboard key, it sets all the sprites invisible except those which are on-screen. This correctly renders what is on-screen, and dropped the CPU usage by half (from ~40 to ~20). So simply by setting all the off-screen sprites to invisible you can save a lot of CPU time. Obviously you don't want to do that every tick since that would be even more work, but if you can once-off set all objects invisible except those in the active area when moving between areas, that measurably helps. It ends up skipping the width, height, bounding box and viewport checks for all those instances.

    Even when you set off the explosions the main increase in CPU is just creating/destroying lots of objects, and more draw calls. That can be optimised more, but it seems an unusual case. Conspicuously absent from the profile was collision checking - that seems to be working great!

    I still find it hard to see why you'd need tens of thousands of sprites in a layout. Remember tilemaps can also draw more efficiently since they can use collision cells when rendering, and if most of your layout design is done with a tilemap, why would you need tens of thousands of sprites? So I'd be curious if anyone can send me more realistic examples, based on actual games or what games at least might realistically do, so I can profile it and figure out if anything's slow in the engine.

    tl;dr - I'm not convinced memory use is a significant issue, and creating and destroying large numbers of objects is actually a lot of work in itself and difficult to make smooth. So if possible I want to aim for a solution where the entire layout exists, and the runtime/events can efficiently handle that, possibly by deactivating but not destroying objects. It's possible to optimise draw calls for large numbers of non-tilemap objects, but I'm not clear that real-world games really need that.

    I think I will write up some of the above advice as a blog post on how to best deal with very large layouts - I think it will be useful beyond those who find it on page 4 of this thread

  • Ashley As far as I'm concerned, performance and memory is not the big issue here..so we can agree on that. The issue is object states inside and outside of rooms. As it stands, we can't revert a room back to its original state, nor can we completely deactivate objects outside the current room without a TON of micro-managing, arrays/dictionaries, families, etc.

    I feel that the actions proposed can solve this with ease.

    -Re-load layout zone to set rooms back to their original state upon entry.

    -Destroy objects outside of layout zones because we don't want anything outside the current room to be active and screw up the game...not because we are attempting to save memory or help performance or whatever.

    That's it. I cannot believe how blown out of proportion these features are. Very simple stuff if using external editors...we just don't have this type of control with C2's layout data.

    As for the ball scenario, 1 makes the most sense to me..but I suppose it depends on the game.

    I'd write more but I'm at work right now ><;

  • Ashley

    Objects with any behavior will consume some cpu time in tick() function executed, so that they could not be ignored I think.

  • Ashley

    Your taking limited image samples and weighing them against what some posters are trying to say. You have some very valid points. When it comes to object space there isn't an issue. object space issue is just getting blown out of proportion. There are different ways to handle object space without any changes to C2.

    However clearing the impression of limited in scope image samples present and instead face the direct situation of achieving goals.

    1. Achieve a purely seamless world.

    The opinion of changing layout is one viable opinion. However we aren't talking 1 option. We are talking about achieving user experience. to provide a true sense of exploration without zoning. For some developers and design this is ok. For other designs and experience saying that just use different layouts is not ok. It's not ok to just say "live with it."

    2. Distinct assets for thematic areas.

    Yes much of the samples use a single graphical asset style and likely the same. However they are used only as a expression of working and sampling large worlds. They should not be mistaken for the limitation of their imagination. However even cities can have very distinct area(river, docks, downtown, suburbs, slums, subway, bridge, airport, parks/forest edge, industrial) and not only is there a visual design distinction there is an audio difference to these areas. At this time by known information there is no way to support these very distinct ares without burning through memory and being open. Zoning is an option, but refer to 1.

    Sample case in an area

    Let's kinda pretend I'm working on a open world like game. The mission, raid a computer mainframe and then escape to the secret hide out in a section of the fictionally clean sewers.

    The player raids the computer to get the data. Corpsec chases after the player through

    building, streets, subway, sewer

    each area is a visual and audio difference and all requires memory.

    Now there are three ways to achieve this chase.

    1. Level design

    In this design the experience is pre-created and meant to have players experience the game in similar to a movie. It's fine if that's the experience the creator wants to achieve. This is also a common design. This however has nothing to do with open worlds.

    2. Layout

    Under this design players can freely go to districts, but require to load a layout. This is the solution offered for open worlds right now. However in a game design experience this breaks down. The reason for this is because when a player leaves the building the adrenaline of the chase pauses. The experience is jarred from escaping the building to the streets. And at each section the player is jarred out of the chase. The zoning works fine for levels because those levels are designed for the thematic feel. Maintaining a frantic feeling of chase is broken and the overall experience is reduced.

    3. Openworld

    Here the player truly has explorable creativity. This entire design scope is meant to let the players be the hero by getting from A to Z their way. As long as A is met and Z is the goal the meandering route is up to the player. Players fight their way out of the building. With no zoning the entire state of the chase remains active. The experience essentially changes. Players hop into a car and drive around interweaving through the street. At times the player will be driving above the physical space of the sewers. Players drive into the subway. Players drive in the subway on the tracks. Players jump out of the car into a maintenance tunnel and head into the sewers. In the sewers the player makes a last stand.

    The entire experience is hugely different for each version, but in all of that we have 4 distinct asset areas. Not only that we have overlapping world space. The sewers and subway occupy the same relative world space. They just don't get loaded until required and we can clear street area. however this does require distinct memory assets.

    When it comes down to open worlds just passing it off as "no reason not to use a layout" is not true. There are very big experience reasons. Grand Theft Auto wouldn't be as big as it is today if the city were just chunked zones. Open worlds are sandboxes and that's a user experience. Which is the entire point of creating games. To provide experiences to the players.

    Now the thing is. Is that an open world sandbox is a niche case.There aren't going to be enought developers to make the case for Sandbox to be an official feature. I personally feel Ashley should not create tools for an open world sandbox. However I do feel Ashley should find a way around any limitation as that limitation does not exist if coding manually, but that's why we like C2 we don't need to code manually. That being said Visual and Audio assets should should be allowed to flag as unload able. And we should find a way to load assets without a pause. Grand Theft Auto manages to load assets with pauses. I know Unity,UE3 can load assets without pausing. I'm pretty sure javascript can load assets without pausing too.


    I agree the performance is not the issue. I disagree about memory. World space is not and has not been an issue. It's about the assets and the assets are memory consuming.

  • rexrainbow - ah true, perhaps a "freeze object" feature could solve that, causing it to maintain its state but go in to a zero cpu mode? Alternatively behaviors can be updated to turn off their ticking when they are inactive. However I guess if we do go ahead with destroying objects then this wouldn't be necessary anyway.

    Tokinsom - it sounds simple to destroy objects outside the active area with events. So could this be narrowed down to a single feature to reset a rectangle of a layout to its initial state? How would that work if you want to specify a list of say 20 object types to reset? (since presumably you want to exclude things like the player, UI, data storage...)

    jayderyu - I don't think images can be loaded mid-layout without creating a pause. There's just no way to do it in HTML5 at the moment. Native engines can do asynchronous texture uploads so big 3D games can get away with it, but it's not supported in WebGL. Even if it was supported you trade it for a new kind of problem: you don't exactly know how long the upload will take, and yet the player can still move around, so how do you guarantee the upload finishes before the player moves in to an area using those textures? If they get there too soon they'll see empty or blank spaces, but if you start loading too soon then you might have too many sets of textures in memory, spike the memory usage and crash. You can release the old textures first but then what if you're still in that area? What if you move back to the previous area while the next set of textures is still uploading? These are really tricky cases and hard to code for. 3D games actually have an advantage in that usually you start far away from a section, where everything appears really small and there's basically no detail you make out, and you can stage it depending on how close you get and how much detail is required. In 2D games you see it full-size and full-resolution immediately, so you can't generally get away with tricks like that.

  • Tylermon

    I believe this is basically what is desired.


    The idea is to save all the objects to a list for each room. Then you could destroy everything and only load specific rooms. Think of it as a mini layout change. It would use more memory but not significantly so. The idea is to mainly provide a way to do transitions between areas, as the loading/unloading of rooms basically is the same as layout changes i a sense. Not to mention it provides for an interesting way to link up rooms in a way that's not a grid more easily.

    The main tediousness to do it with existing events is handling different object types. Multiple sprites is easy enough since you can throw them in a family, but tiledbg objects and any other object would need to be handled separately.

    Also changes in rooms could be saved by reworking it so the object data is one list and the rooms just store a list of object indexes. Then saving an object would just be a matter updating the object data in the list.

  • So basically, don't make small layouts, don't make huge layouts, make medium sized layouts with multiple rooms/ levels, that can lead to other medium sized layouts that have different textures.

    Then perhaps either a modification to the Persist behavior, or a brand new one to remember a destroyed objects state.

  • Ashley Yes I suppose it could. I didn't think about specifying what would or wouldn't be reset, and figured we'd handle duplicates with events or whatever...but it's probably best to allow users to specify what should be reset. In that case we'll need one more action or behavior to do so.

  • R0J0hound Yeah man that's pretty much it. Well done The only drawback to this that I see is, like you said, having to deal with multiple object types...but with families and the ability to store objects as JSON strings, it's really not that bad. Certainly more customizable too since it's all done with events.

    What do you think guys? Can we live with this?

    Ultimately the features we've been proposing here will do exactly what's in R0j0's .capx, but automatically, more or less. Perhaps it is better to do it with events because you have more control over what is and isn't reset - one of Ashley's concerns. It's a bit cumbersome but..oh well?

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)