An example of C3 Spritesheeting Problems

0 favourites
  • 8 posts
From the Asset Store
Unlock platyers earning coins, and save it with Localstorage
  • Ashley

    In another thread you asked for evidence that the auto spritesheeting could be a problem. I ran a test and wanted your thoughts. I cant give concrete numbers because I can't set up my whole game in C3 but hopefully this will show you there needs to be a better method to spritesheeting.

    I recreated how my game is set up but in C3. Here are my test spritesheets:

    The green sprites are the player, the red and blue are enemies, and the smaller ones are fx related to each of those. The green sprites that say "Death" and "Death 2" are animations that should never be loaded together as only one of those is ever needed when the player dies. The green sprite that says "swim" should only ever be loaded on levels that have water. There are also Enemy 1 red sprites which only ever exist on one level. But here it is loaded every time the player is loaded. Also on Sprite Sheet #4 there is a grey star which represents player FX. If I use this player effect, it will load a larger than needed sprite sheet which contains an Enemy sprite, and Enemy FX. Lastly, the red and blue enemy sprites never appear together in game, but they share spritesheets. Every one of these sheets are completely wasteful.

    Keep in mind this is just a small test of a few enemies and FX objects. My player character has 16 standard animations, 5 deaths, 6 cinematic animations, 3 unique level animations...and counting. Most of those shouldn't be loaded unless necessary to optimize as much as possible.

    The most simple enemy in my game has 7 animations averaging 6 frames of animation each.

    There are tons of FX most of which are animated too

    All of those player sprites and related FX would be spread out into multiple enemies and their related FX even if those enemies and FX should never exist together.

    I hope you can see why some type of sprite sheet grouping is necessary for larger games.

  • Construct has no provision for only loading specific animations, it only loads entire objects. This probably won't be changed since loading textures as animations change causes jank (the game will pause momentarily while it loads the textures), so it preloads everything that might be used at the start of the layout.

    In addition to that, the engine already places sprites with 20+ (IIRC) frames on their own spritesheet, avoiding long animations ever being loaded unless they're really used. So this case only crops up when you have a few animation frames, lessening the impact.

    All these sheets together use just under 5mb of memory, which is not much given modern systems have gigabytes of memory. So I don't think it's too wasteful, especially since if all those objects are used together (which they will be for some different kinds of game), it is actually more efficient. Anyways, you get a kind of natural granularity as images spill over multiple spritesheets, so it still doesn't have to load everything at once.

  • Construct has no provision for only loading specific animations, it only loads entire objects.

    I'm sorry I didn't make it clear in this post. In a previous topic, I explained that these are all separate objects. Death, Death2 and Swim are not included in the main player sprite object. At the start of levels that have water in them, I load the Swim sprite that contains SwimIdle, SwimForward, SwimStop, etc so there is no jank. This is good memory management for large games.

    All these sheets together use just under 5mb of memory, which is not much given modern systems have gigabytes of memory.

    This is just a test case. Of course I won't complain about 5mb of memory. But brought out to larger scales, this becomes a problem. If I have huge bosses and C3 shoves in a small FX texture unrelated to the boss, then a huge texture will be loaded whenever I use that FX sprite. This is bad memory management especially for lower spec PCs. You have a whole blog post dedicated to not wasting memory.

    (From another thread)A manual tagging system is boring to do and error-prone (you could easily actually make it worse by getting tags wrong), and the editor has a lot of information it could use to apply grouping automatically, such as inspecting which layouts objects are used together on.

    Being boring is a strange excuse to exclude a feature. There are lots of things in game dev that require boring work but are necessary. There are also simple solutions to avoid errors. Unity lets you create tags, and then just assign that tag to sprites so there are no spelling errors. Thinking about this more, just use a similar system to creating families to create sprite sheet groups.

  • I'm sorry I didn't make it clear in this post. In a previous topic, I explained that these are all separate objects. Death, Death2 and Swim are not included in the main player sprite object. At the start of levels that have water in them, I load the Swim sprite that contains SwimIdle, SwimForward, SwimStop, etc so there is no jank. This is good memory management for large games.

    What measurements did you make that demonstrated this was necessary? If you didn't make any, how do you know this isn't just a waste of time?

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • If you didn't make any [measurements], how do you know this isn't just a waste of time?

    "Remember not to waste your memory" is literally the title of your blog post. And I've just shown that C3 sheets waste memory in a small test case. In larger games, the amount of VRAM used will just balloon.

    Most engines allow you to have control over sprite sheet packing. There must be some reason they allow this, right? If you need links for proof: Unity ,Gamemaker, Stencyl, GoDot, Fusion 3 (which has an automated method using playthroughs)

    From Stencyl's page, "Our goal is to minimize our game's memory footprint. You do that by only loading what you're going to use in your scene."

    What measurements did you make that demonstrated this was necessary?

    None. I've shown that C3's spritesheets are wasteful. I have an 8oz cup that I need to fill with 8oz of milk and C3 will automatically put soda in there. If you are filling up VRAM, you want to be able to control what gets put in. I'm fine staying with C2 since I have that control.

    EDIT: I'm just realizing that you're asking about what measurements I took in C2, not C3. I did do a lot of testing awhile ago (been working on this project for years) and saw the need to break out non essential animations because of memory concerns. I don't have exact numbers at the moment.

  • You can see on the example sheets that the loading of PFX wastes so much VRAM. PFX can fit in a 128x256 texture most likely, but loading it in causes a 256x256 AND a 1024x1024 texture to be loaded. 33x more than the amount of VRAM required. In most use cases this won't matter because you'll be using the other loaded sprites at the same time so they'll be needed anyway, but in certain situations, in games with a lot of art, it could be very wasteful. If every particle effect you load consumes 34x the amount of VRAM required, in a worst case scenario, that's bad. A little bit of control in this area could let devs optimize. Maybe add a field to animations that lets you specify a packing group.

  • Just did an export for a job.

    This was one of the objects setup to use frames as instances:

    I added the background to show the size.

  • And I've just shown that C3 sheets waste memory in a small test case. In larger games, the amount of VRAM used will just balloon.

    That does not necessarily follow. So far I've not seen any reports of someone porting their game from C2 to C3 and the memory use increasing significantly. Almost all spritesheeting approaches will inevitably involve a few extra sprites being bundled in to a sheet, but it's not necessarily a major problem. Actual cases of real-world games using more memory is what would persuade me this needs addressing. Further, it gives me something to actually benchmark, so I can measure there's a real improvement rather than just shooting in the dark.

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