Dynamic loading of assets

Get help using Construct 2

Post » Fri Apr 12, 2013 1:37 pm

I remember some versions ago there was a talk about dynamic loading of sprite on a layout basis, does this still holds true?

I'm getting an out of memory error in Ejecta on an iPad 3 because everything gets loaded at runtime and with the huge pixel density it just runs out of memory, I'm not using WebGL.

What are my options here?
B
29
S
9
G
6
Posts: 525
Reputation: 8,294

Post » Fri Apr 12, 2013 2:22 pm

You could do this manually with LoadImageFromUrl.

With Webgl this should(In the reallity, never :D) work without problems.

For me it worked fine to make a custom Loading screen that loads the images by steps.

Something like:
LoadImageFromUrl
* 10
On Load finished 10th:
LoadImageFromUrl
* 10
....

This is much work but it works. With some luck anyone else here got a better idea.

Hint: With Ejacta and LoadImageFromUrl you can also load images that are already on the phone/tablet.

B
15
S
6
G
6
Posts: 512
Reputation: 5,550

Post » Fri Apr 12, 2013 3:46 pm

Our own layout-by-layout memory loader only works with WebGL support.

In canvas 2D, most browsers are smart enough to implement dynamic texture management in a way which prevents them running out of memory (e.g. release textures which have not been used for a while if encountering an out of memory error). A problem with most DOM-less engines is they make absolutely no attempt to do this and so just crash. The problem is with Ejecta rather than C2, canvas2D doesn't provide a way for us to manually release a texture.
Scirra Founder
B
358
S
214
G
72
Posts: 22,946
Reputation: 178,333

Post » Sat Apr 13, 2013 1:58 am

@Ashley I don't think is so simple because the reply from Ejecta would be to blame construct 2 as loading 100mb of pixels into memory is not a very smart idea.
I think that there is wrong on both sides for sure, but that being said I'll try with WebGL and see if that works, otherwise I'll try @Darklinki solution, even if I think the issue here is not loading them, but the lack of release..
B
29
S
9
G
6
Posts: 525
Reputation: 8,294

Post » Sat Apr 13, 2013 2:15 am

I'd like to piggyback on this, although I will admit I am not too familiar with how C2 handles large scenes.

A lot of modern 3D game engines have portal-loading, in which the next part of a map is loaded once a player reaches a certain zone. For example, if a player gets within 200 meters from the next zone, begin loading the next part in the background. Does Construct 2 have a way to do this, or is this already handled in a much more efficient manner?
Project Lead of Zems Online Card Game

Producer at Impulse Limited
B
18
S
6
G
3
Posts: 677
Reputation: 5,194

Post » Sat Apr 13, 2013 3:20 am

I can report that WebGL still loads everything at startup, why @Ashley?

EDIT: I tested and they do get unloaded, but everything still loads up at startup, all these memory issues would be very easily fixed with an option to avoid any kind of preloading, small images in a local environment would not produce much of a delay, it would be sort of a global LoadImageFromUrl.
0plus12013-04-13 03:58:53
B
29
S
9
G
6
Posts: 525
Reputation: 8,294

Post » Sat Apr 13, 2013 4:13 am

@Excal - textures are loaded layout-by-layout when WebGL is supported.

@0plus1 - WebGL shouldn't be loading everything on startup, how are you measuring that? If you can see VRAM increasing to unusually large levels maybe you should file a bug about it.

However I still disagree, Ejecta is at fault here. Browsers handle it perfectly fine, and if Ejecta's purpose is to allow you to port browser games to native, then it should act like a browser too.

Here's what Construct 2 does:
On startup, it creates an Image object for every object in the project, and assigns its src property. This tells the browser to download it. Browsers do *not* create a texture in memory yet, because they're smart. They either write the compressed PNG/JPEG to a disk cache, or leave the compressed file in memory if there's room. Most DOM-less engines (including CocoonJS) make the mistake of creating a texture as soon as you assign the src property. This means they crash before a real browser would have even created a single texture. Browsers only create a texture the first time you draw it.

When a layout starts:
- in the WebGL renderer, we explicitly create textures for objects that are on the layout.
- in the canvas2D renderer, we draw every image for each object that is on the layout in an invisible way. Since browsers create a texture the first time it's drawn, this effectively pre-loads all textures for canvas2D, and avoids "janking" (pausing as images are loaded mid-game).

When a layout ends:
- in the WebGL renderer, we explicitly free textures for objects that are on the previous layout and not on the next layout.
- in the canvas2D renderer, there's nothing we can do, it doesn't provide a way to say "release this texture" (yet, anyway). Luckily most browsers are also sufficiently smart that if they run out of memory trying to create a new texture, they'll go back, release a bunch of textures that haven't been drawn for a while, then try creating the texture again. It's a bit of a hack, but it does successfully prevent devices running out of memory as you move between lots of different large layouts.

The problem with a lot of DOM-less engines is they are naive, and do the dumb thing of creating textures as soon as the src is assigned. The solution is to make it do what browsers do.
Scirra Founder
B
358
S
214
G
72
Posts: 22,946
Reputation: 178,333

Post » Sat Apr 13, 2013 9:06 am

Could you post a link to your capx? Or a build?
B
50
S
14
G
12
Posts: 813
Reputation: 16,764

Post » Sat Apr 13, 2013 9:16 am

@Ashley

I understand your point, but memory management in these DOM-less engines doesn't look easy to implement, they are partial implementation of a javascript engine, not a fully fledged browser and these kind of stuff is not easily achieved (although it might be implemented in future).

This topic encompass CocoonJS as well as it's basically the same thing as Ejecta (faults included). After testing WebGL does free memory from layout to layout and to be honest iOS wouldn't even mind 100mb of memory. The problem is that during the loading phase there is a huge spike in memory usage, that is because ejecta loads the texture as soon as the src property is set (thanks for the explanation, that was the missing piece of the puzzle) and so the memory gets filled for the whole size of the uncompressed textures (that on a retina display can become quite big).

I'm working on an exporter for Ejecta, I already fixed some issues with the audio object and other little stuff, I would like to try to set a "fake" src property during the loading phase, then set the src the time the object is created, do you think this is possible to achieve? Can you point me in the right direction?

Thanks
B
29
S
9
G
6
Posts: 525
Reputation: 8,294

Post » Sat Apr 13, 2013 12:46 pm

It should be very easy to implement in Ejecta. It's a bit tricky to implement it by hacking the C2 engine.

All Ejecta needs to do is:

1. when setting src, just store it, don't create a texture
2. if the image is used (e.g. passed to drawImage()),if the texture is not yet created, create it; if out of memory, release some textures that haven't been used for a while then try again.

Should be as simple as initialising the texture to a NULL pointer, adding a function 'checkLoadTexture', and calling it in a few strategic places (e.g. at the top of drawImage's implementation). Considering how straightforward it is, Ejecta really ought to support this. (CocoonJS ought to as well, but I think they decided to support it via WebGL instead.)
Scirra Founder
B
358
S
214
G
72
Posts: 22,946
Reputation: 178,333

Next

Return to How do I....?

Who is online

Users browsing this forum: Draconinho, peturfoto and 13 guests