Feature Addition: "Room Object"

Discussion and feedback on Construct 2

Post » Tue Nov 18, 2014 5:52 pm

@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.
Scirra Founder
B
403
S
238
G
89
Posts: 24,653
Reputation: 196,143

Post » Tue Nov 18, 2014 6:06 pm

@Tylermon
I believe this is basically what is desired.
chunk_load_unload2.capx

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.
You do not have the required permissions to view the files attached to this post.
B
94
S
33
G
118
Posts: 5,395
Reputation: 75,851

Post » Tue Nov 18, 2014 6:21 pm

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.
Image ImageImage
B
172
S
50
G
183
Posts: 8,443
Reputation: 115,605

Post » Tue Nov 18, 2014 6:25 pm

@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.
Image
B
243
S
30
G
13
Posts: 1,787
Reputation: 18,770

Post » Tue Nov 18, 2014 6:48 pm

@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?
Image
B
243
S
30
G
13
Posts: 1,787
Reputation: 18,770

Post » Tue Nov 18, 2014 6:54 pm

How would a layout persist behavior deal with multiple instances?
Image ImageImage
B
172
S
50
G
183
Posts: 8,443
Reputation: 115,605

Post » Wed Nov 19, 2014 12:45 am

@Ashley:

Thanks for looking at my test.

I tried to keep this succinct. I failed. I think it's good reading though. ;)

IMHO, C2 already does pretty well with large layouts...barring a few exceptions. Here's my thoughts on that:

1. Example of real-world usage of large numbers of objects:

    a. A MMO, or open world RPG. A game like this could easily have many thousands of objects populating it's expanse.

    b. A Castlevania, Metroid, or Zelda style game with unbroken area/room transitions.

    c. A GTA style game. Yes, many objects in such a game are dynamically 'spawned in', but there are a plethora of props and unique structures. I must admit though...a game like this would probably run into image memory limitations before hitting object limits.

2. Solutions:


    a. Managing large layouts:

    It seems like the best approach would be a version of what Tokinsom is suggesting: Load/Save/Reset/Void layout zone (x1,y1,x2,y2).

    This would be an exception based system, where all objects would be included unless specifically excluded. Exclusion could be done on a per object, per object-type, or per family basis. Certain object types would be excluded by default (Tilemaps).

    There would be an option to store/retrieve this data as JSON (the Load/Save options). For example, we could easily divide a layout into chunks and store them in a dictionary. Then, using the complimentary 'Load from JSON' command, we can spawn chunks back out at will. This is essentially a sort of 'save/load state' command that can function on a user specified area.

    Reset would work as described. Conflicts (the ball scenario) would default to option 1: Destroy both balls, create a new one. There would be an setting (Object Persistence?) under layout settings to change this to option number 4: Create a new object, leave the old ones.

    Void would simply destroy all the non-excluded objects within the specified area. Objects moved into the area would also be destroyed (unless excluded). Objects moved outside that area would not be destroyed.

    For Void/Reset: To handle the lag of creating/destroying all those objects at once, there could be an option to 'lazy load', where only 'X' number of objects would be spawned/destroyed per tick. This would default to 0 (create/destroy all at once). While lazy loading, all objects would be 'inactive' (invisible, no collisions, behaviors inactive) until all objects for the given area were created. Perhaps inactive objects shouldn't even be available to be picked in events (otherwise, event based logic might get messed up).

    b. Size of runtime/data.js file:

    Is there any way this data can be compressed in transit to the user? I notice that dropping my 'Ginormous' 6mb file into 7zip spits out an archive of merely 400kb, a reduction of >magnitude. I have no idea if this is a practical suggestion, but it would be far more effective than truncating object positions, which could be done on our end if need be.

    c. Draw call performance:

    Could the existing collision cells opt be commandeered to set objects more than X cells away from the edges of the window invisible? Since the player is unlikely to be moving across vast expanses in a mere handful of ticks, couldn't this be handled pretty efficiently?

    d. Loading the Layout:

    There is still the initial load of the layout, which, with all the objects present, would be very slow...even if you just proceeded to delete most of them, excepting those near the player.

    One approach is to use the layout zone commands to process the final layout, store the 'chunks' in a dictionary, export said dictionary file to a master JSON, and include said JSON file (WorldDict) with the game. Then, just spawn into a blank layout with identical properties to the master layout, and spawn those chunks out as needed.

    There is still a measure of tedium to this approach, but the layout zone commands would streamline the process immensely.

/tl;dr
Don't lose your work. Backup your game with Dropbox.
B
44
S
10
G
10
Posts: 1,106
Reputation: 9,202

Post » Wed Nov 19, 2014 4:15 pm

@Ashley
That's a very valid point. Playing an open streaming world over the web would result in Second Life effect. Where areas are white shaded blocks until textures load. There is very clear white out until then. From a solid game play perspective this is not acceptable. So playing open streaming worlds online is no good unless of course world building is that experience. So I still wouldn't consider closing the door on asset management.

On the flip side is that the open streaming worlds should only be designed local games. Ie nodewebkit or packed games for mobile. That way the assets are already all there to access and don'y need to be uploaded. Then there is much less load time.

As for unloading and loading of assets. Well cell like structure with let's say screen size + 50% dimension as a sample. The system would keep the screen and 1 cell size around the screen as loaded. When the player transitions a cell the farthest set then starts to unload.

As for teleporation white screen. If Teleportation is needed then use small subset of thematic graphics to each area that works as a world global set of assets. However since they only constitute 10% of each area.

So what I guess I'm saying is that letting players developers have access is important. If it's online world builder games were missing assets are ok and expected and if that's not acceptable such as GTA then the developer and designers can tinker ways around it by using controlled methods. however that capability needs to exist first.

However even GTA and Midnight Club suffer pop in effects. I'll use Midnight Club more. Midnight Club is an open world racing game. I'm pretty sure uses the same base engine as GTA3 back then. Players are given race tracks that consist of markers. however the players are free to get the markers any way they want. Early in the game popup isn't a problem. But I have to admit later in the game on the faster cars and bikes popups do occur. But seems to be handled by distance grid buffering. So even top end games still get hit by missing assets.

I'm not asking for an open world engine. Just a way to flag objects that use images that if there object count is 0, then unload the entire image set. By default this shouldn't happen. I think web focus should have priority. As for asset loading.

If game designers set goals such as no more than 2 thematic areas at one time. Then world design can take that into account and avoid issues. Developers are crazy nuts that can figure out possible solutions. Providing there isn't anything blocking them. However memory overload is a blocker.

And as you say since WebGL can't do asynchronous loading, and at this time looks like WebGL can't do webworker ascyn loading. Then there is a blocker in the WebGl. So not much can be done at the moment. Pity. But maybe in 6 months.
B
92
S
18
G
9
Posts: 2,455
Reputation: 15,113

Post » Wed Nov 19, 2014 7:09 pm

So I'm thinking the best solution so far is simply an action to recreate the initial instances in a rectangle of the layout for a single object type. It would not destroy anything, since you can easily use a Destroy action to destroy everything yourself if that's what you want to happen, so you can have it both ways (either destroy and create, or keep everything and create).

Since it only works for one type, then you could simply call a function which has a list of destroy/recreate actions for every object type you want to opt in to this resetting. Then you can use that function to reset arbitrary rectangles of the layout to its initial state for a specified list of objects. This doesn't involve saving and restoring any state, which I think is for the best anyway - that adds a lot of overhead (especially if they are static background objects or similar), and it can be done with events in cases that you want it as well. Or you can leave them still existing there and destroy the things around it, or we could still look in to ways to make leaving everything still perform well.

I reviewed the engine code and creating objects should actually be pretty fast, but destroying large numbers of objects at once was slow. I've done some optimisation work for the next beta to make that a lot faster (I got one stress test running several times faster). So that should help make the destroy-sections approach work better.

TiAm wrote:Is there any way this data can be compressed in transit to the user?

I think most servers on the web have default settings that automatically apply compression to all text-based formats. So this should happen automatically with most servers.

TiAm wrote:Could the existing collision cells opt be commandeered to set objects more than X cells away from the edges of the window invisible?

Maybe - I wanted to when it was first implemented, but it's difficult enough that I couldn't figure out a good way to do it. The main complication is Z order. Collision cells don't care about ordering instances - they are simply either in it or not. Objects can belong to multiple collision cells at once, and multiple collision cells can be on-screen. So then how do obtain just the on-screen objects and then render them in their correct Z order? It's difficult to see how this wouldn't involve something like "gather everything on-screen then sort by Z order", but running a sort on all on-screen instances every tick could cause very poor performance for games with a small layout and a very large number of on-screen objects (e.g. bullet hell). There are possible solutions which don't require continual sorting, but they are pretty complicated. I'll think about it some more, it would be nice if it could be solved...
Scirra Founder
B
403
S
238
G
89
Posts: 24,653
Reputation: 196,143

Post » Wed Nov 19, 2014 9:24 pm

Sounds good to me :)

I think saving object states should be done with events as you said, so we can store them in arrays/webstorage for later on. Anything built in would only be for that session which isn't very useful imo.
Image
B
243
S
30
G
13
Posts: 1,787
Reputation: 18,770

PreviousNext

Return to Construct 2 General

Who is online

Users browsing this forum: Yahoo [Bot] and 4 guests