The future of the Construct 3 runtime

2
Official Construct Post
Ashley's avatar
Ashley
  • 4 Apr, 2017
  • 2,479 words
  • ~10-17 mins
  • 4,822 visits
  • 0 favourites

When we first announced Construct 3, we said we'd focus on redesigning the editor, and carry over the same runtime as Construct 2. This was a wise choice given the vast scale of the project — rewriting the editor from the ground-up with radical new technologies was certainly enough to keep us busy for a few years.

However we were never going to use the same runtime forever. Now that Construct 3 has reached public beta, we want to tell you about our next major project: it's time to rewrite the runtime too. This will be our next major project once Construct 3 has stabilised and is ready for its full launch.

The Construct 2 runtime

Technology moves fast. The Construct 2 runtime has served us incredibly well, but now it is showing its age. It was originally written back in 2011 when Microsoft's latest browser was Internet Explorer 8 (which didn't run HTML5 games at all — that came with IE9), and there was no sign of WebGL, Web Audio or many of the other technologies which power modern web games. It's hard to overstate just how much the web platform has changed since then. The runtime also still has a lot of compatibility code, workarounds and quirks aimed at platforms that are pretty much irrelevant today, such as IE9-10, defunct Android stock browsers, and a couple of generations of non-browser engines like directCanvas (remember that?) and Ejecta that are all now deprecated.

On top of that, much of the architectural foundations of the Construct 2 runtime were written back when Scirra was a scrappy startup under pressure to get a working product out the door as soon as possible. Much of the early foundational code was written accordingly. This was the right approach at the time, but the consequences of that are now starting to constrain what we can do with the engine.

As a result the runtime code is increasingly difficult to work with, and adding major new runtime features would be challenging. It needs modernising. This is also partly why most new Construct 3 features are in the editor only. This will ultimately make it possible to do entirely new things while making the code far easier to maintain and improve. There's also a lot we can do to make significant performance improvements with a redesign.

The Construct 3 runtime

Developing Construct 3 has given us a unique insight in to the web platform and the browser engines that power it. We've learnt a great deal and we are keen to apply this to a new Construct 3 runtime. In a number of cases, we already have substantially improved code in Construct 3 which we can directly re-use in the new runtime, such as the new WebGL renderer. We can make similar improvements throughout the entire engine. Here is an outline of our goals for a new Construct 3 runtime.

  • A complete ground-up rewrite with a carefully designed foundational architecture, designed to be robust, maximally performant, and with long-term durability
  • Use modern, scalable and maintainable coding practices we have developed and fine-tuned throughout the development of the Construct 3 editor. This also means making full use of the latest JavaScript standard, which has a broad array of new features that significantly improve code quality, and new data structures that can boost performance.
  • Re-use Construct 3 editor code, sharing as much code as possible between the editor and runtime, speeding up and simplifying development
  • Streamline the codebase by removing old compatibility code for old browsers and platforms now out of use, making the code easier to work with.
  • Settle on a single set of modern web platform APIs. Construct 2 has a lot of fallbacks like canvas2d rendering or HTML5 audio, which increases the maintenance burden and complicates adding new features. By only supporting WebGL, for example, the engine is substantially simplified and it becomes much more straightforward to add advanced new rendering features.
  • Optimise the engine to remove some long-standing inefficiencies. Wide-ranging changes can be made such as reducing preview/startup time, reducing memory usage in large projects, and using monomorphic coding practices to reach peak performance in JIT compilers.
  • Make greater use of asynchronous features and multithreading to make better use of multi-core CPUs and use techniques like preparing textures in parallel to speed up loading layouts
  • Enable hosting the runtime in new environments like a Web Worker, or a headless mode in Node
  • Architect to make major new features possible like modular events, improved functions, and sub-layouts
  • Implement a more formal API for plugin developers using the SDK, exposing more features and better documenting the capabilities

What about native?

We outlined our reasons for sticking to a HTML5 engine in the case against native engines. Users still sometimes suggest native engines, and we're still not convinced. Too often we see users suggesting native engines as a knee-jerk reaction in response to a problem they are having, without any consideration for whether a native engine would actually solve that, or be worth the corresponding trade-offs. For example we regularly see users blame HTML5 even when the problem stems from hardware limitations like GPU bandwidth. In one case a user disabled most of Construct 2's optimisations, and still first assumed the problem was HTML5. Our routine investigations in to user's everyday problems rarely turn up issues that would be genuinely improved with the use of native technology. Of course, HTML5 does have some problems, but ultimately no platform is perfect. Switching technology won't mean there will be zero problems either.

Ultimately while we do recognise that like any technology web technology is not perfect, we do see an element of anti-HTML5 bias in people's perception of the technology. So while it may seem surprising to some how we still resist native engines, our perspective is that overall it is really working very well. And as ever the web is continually advancing. For example GPU blacklisting used to be a big problem, but now only affects around 4% of devices and is still shrinking. At the other end, WebGL 2 represents a major upgrade in the rendering capabilities of the web platform, and was only just recently released. The pace of improvements is still going strong and web technology is more robust than ever.

What about WebAssembly?

WebAssembly is certainly an interesting technology, and one we feel is more compelling than a complete shift to fully native technologies. However while performance is obviously a particularly important consideration, in practice there are many other aspects of development to take in to account. One significant lesson we learnt back in the times of Construct Classic was that obsessively optimising the engine can actually result in labyrinth complexity in the engine, extremely difficult bugs, and important user-visible features that get postponed while all that is dealt with. It is unwise to relentlessly chase performance at the expense of everything else.

Making development and maintenance as easy as possible helps us move quickly with the engine, and are also essential considerations. Some of our concerns around using WebAssembly in the engine include:

  • WebAssembly is a young technology, and the tools and support for it are fairly rudimentary at this point relative to more mature technologies, especially in aspects like debugging. It also currently lacks direct access to browser APIs, which would complicate the runtime architecture.
  • Compiling to WebAssembly typically involves working with statically-typed compiled languages. These have their strengths, but involve slower iterations with stricter languages and ahead-of-time compilers. We've really come to love the development velocity of modern JavaScript.
  • Construct 3 uses a highly modular architecture with each plugin and behavior independently written. It's valuable for third-party developers to be able to use an accessible language like JavaScript, and it's also great for us to easily add official plugins and behaviors too. Even with a WebAssembly engine we'd still want to use JavaScript for many official addons where maximum performance is not a significant concern, such as with media, networking or form control related plugins. Interoperating JavaScript and WebAssembly is more complicated than just using JavaScript everywhere, and can involve a performance overhead. In fact the Construct 2 runtime switches between the engine and plugin code at such a high frequency that even a small performance overhead to the switch would likely wipe out any benefits of using WebAssembly.

Especially given the last point, we feel that using WebAssembly is pretty much an all-or-nothing proposition: either the entire engine, and all plugins and behaviors, are written in WebAssembly, or none of them are and we stick to JavaScript everywhere. We've decided on sticking to JavaScript everywhere. Some of the reasons for this are:

  1. As mentioned, we believe we can do a lot to significantly improve performance already, without having to change from JavaScript.
  2. We want both plugin developers and ourselves internally to be able to easily and quickly develop addons.
  3. It also makes it easy and quick to develop the core engine.
  4. We can also directly re-use code from the editor, like the new WebGL renderer, rather than having to re-write and then maintain these components in a different language.

So on that basis we have decided to stick to JavaScript for the new engine. We will still experiment with using asm.js/WebAssembly to achieve maximum performance with specific features that can benefit from that, like the physics engine which already uses asm.js.

The three runtimes

To clarify our development approach, once we start the Construct 3 runtime, we will actually be maintaining three different runtimes:

  • The Construct 2 runtime in the Construct 2 editor (C2): this will see continued maintenance much as we have done for Construct 2 over the past year.
  • The Construct 2 runtime in the Construct 3 editor (C2.3): this is the Construct 2 runtime with some modifications to be compatible in the new editor, as well as various upgrades corresponding to Construct 3 improvements, such as improved spritesheeting support to work with the new in-editor spritesheeting
  • The Construct 3 runtime in the Construct 3 editor (C3): this is the new runtime we are discussing developing in this post.

The rest of this post is focused on transitioning to the new runtime in the Construct 3 editor only. We'll use the terms C2, C2.3 and C3 for the runtime as above to make it clear which we are talking about.

Transitioning to a new engine

We will go to pains to ensure the new C3 runtime is compatible with the previous runtimes. This can prove difficult though, and in some cases we may want to deliberately change behavior to achieve better performance or make the engine more robust in the long-term. We'll carefully document as many of these cases as possible to make porting content to it easier.

Porting addons to Construct 3 has so far only involved rewriting the editor side of the addon. Porting third-party addons to the new C3 runtime will involve rewriting the runtime side as well, which is often a bigger job. One of the reasons we want to do this as soon as possible after the launch is to get a head start on porting, which is likely to be an on-going project. Looking in to the long-term, hopefully this will be less of an issue once it's out of the way. As with the editor side, we will provide comprehensive documentation of the new SDK and assist developers with porting guides.

Finally, the new C3 runtime will probably take a long time to develop to a mature level. We will continue to maintain the C2.3 runtime throughout that time. (Separately, the C2 runtime will be also be maintained as part of Construct 2's ongoing maintenance.) Additionally once the C3 runtime is available, the C2.3 runtime will still be available and supported for the foreseeable future after that. Ideally we can eventually one day drop support for the C2.3 runtime, but we recognise many developer's projects span years of development, may rely on third-party addons that are only available in one runtime, or may be too complex to port to a new runtime with some differences. Therefore you will be able to select which runtime a project uses. You'll also be able to switch runtimes if your project is compatible, so you can try out existing projects in the new runtime, and keep using it if there are no issues. Hopefully this brings the best of both worlds: predictability for long-term development projects that rely on the C2.3 runtime, and new features and improved performance in the C3 runtime for new projects or any existing projects that can be ported.

We'll make the new runtime available in a few phases. Currently it still needs a lot of work. However here's how we'll roll it out:

  1. Once it's ready for simple tests, it'll be made available as a hidden option for experienced users to try out, and for plugin developers to get a head start on porting.
  2. As it developers further, it'll be made a visible but off-by-default option so it's easy to try it out.
  3. Once we're confident with it, new projects will use the new runtime by default, and only existing projects will remain with the old runtime. Even then they can be upgraded by manually switching to the new runtime.

New features ahoy!

Once the architectural work is done and projects are able to be ported, we'll have a much faster and better base to build major new features on top of. We're keen to address many long-standing requests with the new runtime. Some of the new features we'd like to build on it include:

  • Modular event features, aimed at capabilities like building plugins out of events
  • Advanced rendering features like mesh distortion
  • Rudimentary 3D capabilities like adjusting the Z height of a sprite, and exposing more capabilities to the SDK
  • Sub-layers for advanced lighting and blending effects
  • Sub-layouts for embedding other layouts, creating split-screen views and more
  • Redesigned first-class support for functions
  • A built-in color filter feature similar to what we had back in Construct Classic
  • A set of new plugins ranging from custom drawing canvases to integrating HTML content
  • Add lots of long-standing plugin requests like rotatable 9-patches, scale and rotate Tiled Background image, and more
  • Even more ideas in future!

Conclusion

Creating a whole new runtime for Construct 3 is an enormous project and will take some time. However this is the next major step in the evolution of Construct. It will modernise the engine, make exciting major new features possible, and future-proof us for the years to come.

As before, our first priority will be to ensure the Construct 3 editor is stabilised through the public beta and ready for the full launch. Once that's done though we are excited to get started on this next major advance in the development of Construct!

Subscribe

Get emailed when there are new posts!