Ashley's Forum Posts

  • Changing Z order in a loop is inefficient because it changes the Z order repeatedly. The 'sort Z order' action is efficient because it does the sorting, then changes the Z order once at the end. So you should basically only use the 'sort Z order' actions for large numbers of instances. However if you just update the instance variable it uses in a loop, that's fine, because updating an instance variable doesn't itself change Z order.

  • Nice to see an initial version appear so quickly!

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • I don't think these other cases are the same polymorphism issue.

    I noticed a hit of around 40%, even when the solid behaviour was set to disabled.

    Currently the C2 runtime unconditionally ticks all behaviors. The solid behavior does not need ticking, so this is wasteful when you have a lot of instances. The C3 runtime is smarter and only opts in to ticking the behaviors that need it. So I tested this as well and in the C3 runtime, adding a solid behavior does not impact the performance in the quadissue test. (This isn't polymorphism, it's just better design.) Some behaviors do need ticking though (generally the movements), there probably won't be much change for them, but for those it has to do per-tick work anyway so it's necessary.

    [quote:15a6nvsr]EDIT2: Adding the effect grayscale on the sprite game me 32000 max sprites, where as original was 180.000

    But adding the same effect to the Layer instead of the sprite showed now significant drop.

    Rendering effects has quite a high overhead per effect, and using a layer effect instead when you have a lot of instances is already in our performance advice. Rendering effects is complicated so there will probably be quite a high per-effect overhead in the C3 runtime too, but this also isn't polymorphism, it's just that rendering effects involves extra work.

  • We don't want to put out the full source of the built-in plugins in C3, because in C2 this basically caused ongoing compatibility nightmares, to the extent I'd rather simply block the option of copy-pasting an addon to tweak it, and force us to come up with another way to alter other addons in an extensible way. You can however see the runtime scripts in preview mode, as pointed out. If you have any questions about the SDK I'll try to answer them on the forum.

    The point about loading project files is a good question, because it's different in C3. Preview mode doesn't actually host on a server, it keeps everything locally, so there's no direct URL to project files. You can solve this by asking the runtime for the URL to the resource with:

    var urlToRequest = this.runtime.getLocalFileUrl(projectFileUrl);[/code:132x49b4]
    
    In preview mode, urlToRequest will be a blob URL that you can fetch normally and will load the project file locally. After export this just passes the URL through and fetches it from the network as usual.
  • It's not been planned in much detail yet. It's an important goal, but is probably some way off at the moment, since we want to have the C3 runtime in place first, and then probably significantly revise the way functions work after that.

  • Just out of curiosity i ran the C3 performance test quad issue with and without Families as well.

    I can measure somewhere around a 30% hit when you add a family to the sprite being benchmarked. I would guess this is the polymorphism issue, which I've always suspected was an issue, but never found a way to isolate the overhead of - so this is an interesting test because you've found a way to highlight it!

    If I'm right, this is a somewhat complicated issue. It will probably be an on/off thing, i.e. either you get a fixed performance hit to the project, or you don't (I don't think it will get worse if you keep adding families, but maybe we should benchmark that too). It comes down to the way JavaScript JIT compilers work. At the moment the C2 runtime uses lots of different kinds of JavaScript "classes" (sometimes called object shapes in the engines). In this case there's a different class for a normal object type and a family, and in some parts of the engine both of these classes are used interchangeably in the same functions. JIT compilers optimise on what the code really does, and if you don't use families, all those functions use just one kind of class, and so the code is optimised for a single class (monomorphic code). As soon as you throw a family in to the mix, which is a different class, it has to change the optimisation to be able to handle multiple kinds of class (polymorphic code), which is slower since it involves checks for which kind of class is being used. There's a lot of this kind of thing in the C2 runtime, basically by accident. It's always been a goal of the C3 runtime to completely restructure all the code to remove all this polymorphism, which is why I mentioned "using monomorphic coding practices to reach peak performance in JIT compilers" in this blog post.

    The good news is... I've actually got enough of a working prototype of the C3 runtime to benchmark this already, and the C3 runtime does not have any performance impact when you add a family. So this is a nice confirmation that the new engine is indeed going in the right direction with its architecture, and should fix this problem throughout the engine. This could mean quite a big performance boost for large projects!

  • Ashley does Construct provide a debug mode and logging to determine why I am getting this disturbing behavior?

    No, only we have the developer tools necessary to investigate issues, and in order for us to use them we need a way to reproduce the issue ourselves.

  • lucid - you've raised some good points, actually. Let me have a think about what we could do to solve some of these integration problems.

    For rendering deformed meshes, are you currently drawing degenerate quads? (i.e. make two points of the quad the same, so you get a triangle)

  • I really, really would so much prefer Spriter and Spine to not implement themselves as drawing plugins. This forces the plugin to reimplement a bunch of Construct features and actually limits other creative features too. For example:

    • you can't add a WebGL shader to just one part of a skeletal animation if the plugin draws the whole thing, but you can if it just controls sprite objects (e.g. make just the head flash red if hit, etc)
    • you can't test for collisions with just a segment of a skeletal animation if the plugin draws the whole thing, but you can if it just controls sprite objects
    • a plugin which draws the whole animation probably has to reinvent a whole asset management pipeline, but if it just controls sprites it leverages our project-wide in-editor spritesheeting engine
    • Construct's support for containers allows you to treat composite objects as if they were one instance in the events

    Personally I am convinced that these plugins should not use the drawing APIs and should simply act as controllers for sprites. This makes it much more flexible for the user, and avoids clunky reinventions of existing parts of Construct. I discussed this at length with a Spine developer a while ago and I thought they agreed; one of the outcomes of that discussion was the decision provide a custom import process so they can conveniently generate all the necessary sprites on import, so I filed this issue as a TODO for that work. Perhaps not all the Spine developers are aware of this approach.

    We could add the drawing APIs they want, but one of the reasons we're holding off is because those features don't work in the canvas2d renderer. From the user's point of view, this will manifest as the plugin randomly not working on a small percentage of devices. I intend to make the C3 runtime the point where we unilaterally drop the canvas2d renderer, at which point we can go to town with these kinds of features. However even then it has the drawbacks listed above, and the C3 runtime is still some way off.

    Rather than adding new drawing APIs, I would much rather add any extra APIs to allow them to act as controllers, and have a good workflow for importing and updating. That's why I filed the custom importers TODO issue. I am totally willing to co-operate with any developers who want to take this approach and refine the SDK to make it work well. I can't force them to, and they might make drawing plugins anyway, but I hope at least one of them take me up on this offer!

  • Please read the bug report guidelines. The goal is to produce the smallest project possible that reproduces the issue.

  • Can't reproduce here, it exports and runs fine.

    Please see the bug report guidelines so we can better help you: try testing with the latest release (r249), avoid using third-party addons, and try to narrow it down to a minimal project that reproduces the issue.

  • lucid - use developer mode so you can just fix the problem and carry on.

  • As I said, the engine is designed to not do any extra work when you add objects to families, because obviously this would be a scalability issue. I stepped through the debugger with the given project and verified that it isn't doing any extra work, but the time taken do to the same work appears to increase anyway. Either I missed something, or there's a weird effect with the JIT compiler adjusting the optimisations as families are present, which wouldn't be surprising since there's a lot of accidental polymorphism in the C2 runtime. It might have to be something that we revise in the C3 runtime.

    Still, getting to 100,000 objects isn't too bad!

  • blackhornet - ah, good point about basic ACEs, they were actually implemented but not documented. I've updated the documentation to include them.

    The hotspot features are there, they were just renamed to "origin" in C3. See the origin functions here.

  • As for Construct 3 r68, the plugin SDK supports drawing plugins.

    The plugin SDK download has been updated, and now includes two example plugins: a single-global plugin (the same one that it had before), and a drawing plugin (the new one). The drawing plugin simply displays a single image and provides the options to edit the image, size it to original size (like Sprite), and also a C2 runtime implementation that draws it from a spritesheet.

    Note that in C2, not all images were spritesheeted. In C3, all images are spritesheeted, so plugin drawing methods must take this in to account. The example C2 runtime implementation has code that demonstrates this for both the canvas2d and WebGL renderers.

    All available editor APIs are now documented in the editor API reference section of the Addon SDK documentation. To fully support drawing plugins, many new interfaces have been added, and they are comprehensively documented there.

    This is an initial release and the capabilities are fairly basic. If you are developing a plugin that needs some extra APIs, please let me know in this thread and I'll see what we can do about it. I'd expect it to take a few more releases of C3 to fully mature the APIs and cover everything that third-party developers need.