Exploring possible issue with Sprite Load image from URL?

0 favourites
From the Asset Store
Minimal Sprite Font with Stroke for Pixel Art games.
  • I'm working with an animation runtime which is rendering via webgl to a separate canvas.

    I want to use the result of the render as the image for a Sprite in C3. I would like to change the image for the Sprite on every frame (to show the animation.)

    I am using the Sprite Load Image from URL action (using a blob URI or a data URI that has been captured from the separate canvas) to set the image of the Sprite.

    It's working pretty well, except for a stutter I get every few seconds. Tracking it down, it _looks_ like it's due to v8 running 'Major GC' and pausing the rest of execution for a while. Is there something in the Sprite Load Image from URL action that would cause 'Major GC' to kick off every few seconds?

    I have created a simplified test case which shows the issue (in this case I created a JSON object of data URIs instead of capturing another canvas and using the animation runtime, to help isolate the issue to just the Sprite Load Image from URL action.)

    Looking at the perf graphs, a big system task is kicking in, then 'Major GC' starts.

    I thought I would start here for discussion, but if needed, I can also file a bug report.

    Example Project:

    LoadSpriteURLTest.c3p

    I am also very open to other ways to do a load of the sprite texture each frame if that would work better (within the JS C3 SDK or other C3 actions, etc.)

  • Does it have to run constantly? Can't you just initially render and load all the required frames/animations?

  • Yeah the question is why do you need it in text form. Png is already a compressed format, and is pretty much guaranteed to be smaller.

    Otherwise I think a better solution would be to paste sprites into Drawing Canvas, and save that image into a Tiled Background object. You can animate it via x, or y offset.(as an alternative to trying to load to frames)

  • newt WackyToaster Thanks for the comments. The example project was done just to isolate the stuttering issue to a C3 action. The full project includes the Spine JS webgl runtime (skeletal animation, similar to Spriter 2, Dragonbones, etc.) which does full animation, including dynamically mixing between animations, skinning, many animations, etc.) The Spins JS runtime allows for dynamic control, so the animation rendered will not be just one small animation loop that captured and replayed. It needs to run constantly. I just did the JSON data URI / string replay in the example to show the stuttering issue in an isolated way without all the baggage of the Spine JS webgl runtime.

    In the full project, I have tested with using a blob (binary/png) URI and a data URI (text.) with similar results.

    I am hoping that Ashley or others can take a look at it since it seems related to the C3 runtime/plugin implementation of the Load image from URL action (or have a suggestion on an alternative workaround that allows a Sprite image to be updated every frame.)

  • Doesn't Spriter make brand new objects for each limb?

  • Hmm I'd guess that loading 60 images per second may be a bit of an issue here. All of them end up in memory and are discarded the very next frame, aren't they?

    Btw your example runs buttery smooth on my phone, it does drop 1-2 frames every now and then but it's not noticeable.

  • newt you are right, it does. It looks like a lot of work to port the full Spine runtime from JS / webgl to the C3 SDK (including managing textures, animations, etc. in the C3 SDK, dealing with deforming meshes and degenerate C3 quads rendered to texture with proper texture projection.) So, I'm trying to take the shortcut of using the Spine JS/webgl runtime pretty much as is and push the final rendered output to a sprite (except loading atlas and skeleton from C3 project files.)

    WackyToaster Yes, that's what happens, with the blobs, I'm trying some tricks like URL.revokeObjectURL() on the blob URI to give hints to the GC to do Minor GC over time, instead of Major GC. I also tried using the data URI, so at least I'm not creating blobs as I capture the canvas, however, I imagine that the Sprite Load image action may be creating blobs for the new image it's loading from the data URI (perhaps adding a URL.revokeObjectURL() to old blobs in the implementation of the Sprite Load image action would help, but this is all speculation.)

    With the full project, it's similar, very smooth, but then every few seconds there is a stutter. I'll post the full project in another thread later, it's WIP, but promising!

  • Ok, well how about using the load json feature instead?

    It would require editing the json to accommodate C3's format, but it's not that big of a hoop.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • newt In your suggestion, what would the JSON data to be used for and what object would it be loaded into? I'm not sure how this helps to load a sprite image.

  • Ok, well the question is does the Spine json contain anything other than the image?

    Edit:

    Nevermind, I see this is basically like a movie.

    I don't think this is a good way to do it.

  • That JSON is just in the example to focus on the Sprite Load image action. In the actual project, the blob or data URI is generated from the capture of the Spine rendered canvas, each rendered frame and JSON is not needed or used. The JSON in the example was a capture of three of the data URIs generated in the full project.

    The blob or the data URI contains only the image. They will change each frame depending on the game's control of the Spine animation.

    I am hoping for more suggestions around loading a Sprite image each frame without the engine stuttering.

  • I don't think it's a good idea as a whole to continually load image data. I don't know the inner workings of the engine, but I believe it's not optimized in any way to do something like that.

    What could work, however, is to create a lot of placeholder animations and animation frames. During your loading phase, preload all of the image data into said placeholder animations/frames. You'd be able to use C3 animation engine that way, although you could also set every animation speed to 0 and create your own.

  • Magistross Thanks for the comments, if I wanted to preload the animations, I could also use the Spine tool itself to playback animations and create many png spritesheets to import into the C3 editor. However, for high frame rate and many animations, this would be a lot of PNGs to store. I would also have to add all the variations for mixing different animations (you can 'tween' between, so they transition well.) It would also have to be done for every skin (you can see how this explodes quickly.) It's similar to why some people use the Spriter plugin, instead of using captured Spriter png spritesheets. I do want the dynamic Spine animation control during game runtime (to control animation mixing, skinning, etc.)

    That being said, your suggestion may be an improved workflow to doing Spine png export and I will definitely keep it in mind (you can even do some optimizations like change render resolution for preloads during runtime depending on the device you are on.)

  • Well, the bottleneck here is really the multiple calls to "Load image from URL", so as long as it stays the only way to edit a sprite's image data, achieving something truly dynamic AND performant seems out of the question.

  • Magistross Agreed - though it seems pretty close to working. It works well for 100s of frames before it stutters, so I'm hoping Ashley can give some guidance on how to improve this, perhaps using a function of the C3 Plugin SDK or Scripting SDK instead of the Sprite action, or if there can be some improvement done to my use of the Sprite Load Image action (or if it's possible to change the C3 implementation of the action so the Major GC does not occur.) The Load image w/ blob takes up < 1ms of frame time, so pretty usable.

    Here's a short loop that shows it works well for a second or two (this is from the full project, Spine webgl runtime integrated with C3 via Sprite image loaded from separate Spine runtime webgl rendered canvas and outline effect applied on Sprite.)

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