Skip to main content

11 posts tagged with "engine"

View All Tags

Transitioning to the New Render Component and Fill Mode API

· 5 min read
Steven Yau
Partner Relations Manager

Hi everyone!

This is a different blog post to what we normally do but with some big changes coming soon, we wanted to give context and advance notice of said changes and more importantly, how they may affect you across the PlayCanvas platform.

Moving from Model Component model import pipeline to new Render Component

As part of the work to enable the import of a model’s hierarchy into the scene, we have introduced Render Asset and Render Component as new features of the Engine and Editor.

Import Hierarchy Preview

Going forward, this will be the default way to render imported models and gives developers greater flexibility in manipulating mesh instances in the model directly in the Editor. For example, with the new pipeline you can import a house FBX model and only use the door mesh instance in the scene instead of the whole model.

However, please note that while the Model Component is compatible with both the Animation and Anim (State Graph) Component, the Render Component/Import Hierarchy feature is only compatible with the Anim (State Graph) Component.

(More details will be shared in an upcoming announcement, stay tuned for that!)

For existing projects using the Model Component, please do not worry. None of the existing functionality is being removed and you will not be forced to update projects to the new pipeline for continued development. Although no new features will be added to the Model Component, the PlayCanvas team will continue to fix bugs with the existing pipeline.

You can even mix both pipelines in the same project if you wish to take advantage of the features in the new pipeline in an existing project. However, please bear in mind that this can add complexity to the project code.

The expected changes over the upcoming months are as follows:

  • Add/Rename a Project Setting to switch between the two mesh import pipelines (Currently, this is the ‘Import Hierarchy’ setting).
  • Newly created projects will default to using the Render Component pipeline.
  • developer.playcanvas.com tutorials will be updated to use Render Component (playcanvas.github.io engine examples have already been updated).
  • The template projects (Blank Project, Model Viewer Starter Kit, VR Starter Kit) will be updated to use Render Component.
  • User Manual updates and mitigation steps from using the Model Component to Render Component pipelines.

Breaking change to PlayCanvas Fill Mode API

We want to make the PlayCanvas engine as flexible as it can be for the widest range of use cases for web developers. To do so, we occasionally have to break existing APIs that may have made sense when they were first introduced, but not today.

One such API is the Fill Mode related functions on pc.Application:

These functions affect the canvas element size in the DOM as it was long assumed that apps made with PlayCanvas are either be iframed or fullscreen/full document apps.

However, there has been more requests about having more control of the canvas element rather than using iframes. The main reason is that it’s easier to communicate between the page and the PlayCanvas app without having to deal with iframe messaging.

Some examples:

Currently, there is no way for an end user to have full control of the canvas without patching the engine.

Also, from an architecture point of view, the Engine shouldn’t handle the size or position of the element that it is rendering in. The responsibility should be on the web document and how it wants to layout the elements on the page (e.g through stylesheets).

These changes will affect you directly if you are:

  • An engine only user as the HTML boilerplate will handle the resizing and positioning of the canvas. We will provide examples in the examples folder.
  • Any developer that changes the fill mode or resizes the Canvas at runtime. Some developers do this to handle landscape and portrait mode more effectively.

The current plan is deprecate these functions and move them to globally accessible functions on the page on the PlayCanvas Editor environment with as little (if any) downtime for projects or developers. At worst, you should only get a few warnings in the console log regarding deprecated function use.

The steps will be as a gradual rollout:

  • Add globally accessible JS functions in the Editor and publish HTML templates to replace the fill mode functions from the Engine.
  • Change the PlayCanvas Editor and published build templates to patch the Engine functions to call the global functions above with warnings that they should use the global functions instead.
  • Update the User Manual to document these global functions.
  • Deprecate the affected engine functions with warnings and reference the User Manual page.

Questions and Feedback

If there are any questions or areas that you would like to be made more clear, please post in the forums and the PlayCanvas team will be there to answer.

The PlayCanvas team are appreciative of your patience and continued support as we go through this transition!

Porting a Large ES5 JavaScript Library to ES6 Modules and Rollup

· 5 min read

Since 2011, the PlayCanvas engine sourcebase has adhered strictly to the ES5 JavaScript specification. Since then, the JavaScript language and the surrounding tools ecosystem has moved on considerably. But PlayCanvas has steadfastly stuck to ES5. Why? Internet Explorer 11.

IE11 was released on October 17, 2013. But even today, StatCounter reports that IE11 has 2.43% of the global desktop browser market. Since PlayCanvas content is viewed by 100s of millions of end users, this is a pretty big deal.

Over time, the engine codebase has grown significantly. It's now nearly 100,000 lines long. Maintaining and building such a large codebase can be problematic. To help bring some level of consistency and structure, we imposed the following pattern:

Object.assign(pc, (function () {
var SomeClass = function () {
this.other = new pc.OtherClass();
};

Object.assign(SomeClass.prototype, {
someFunction: function () {}
});

return {
SomeClass: SomeClass
};
}()));

pc is the PlayCanvas library namespace. So a developer would create instances of this class as follows:

var thing = new pc.SomeClass();

To build the engine, we wrote a node.js script which would parse a list of dependencies (JavaScript filenames) and concatenate them. There were several problems:

  1. The pattern above is overly verbose making it harder to inspect the code.
  2. Object.assign needs to be called 250 times when the library is initially executed by the browser, once for each module. This increases app start-up times.
  3. In internal engine code, all class names and constants need to be accessed via the pc namespace. This is because the internals of the pattern above cannot see the internals of other modules and vice versa. This bloats the engine code and slows things down.
  4. The dependencies file had to be carefully manually ordered to ensure things were declared in the right order.
  5. The build script itself was about 1000 lines of JavaScript which carried its own maintenance overhead.
  6. Unused code was being included in the published engine.

We believed the solution to these problems was to migrate the engine codebase from vanilla ES5 to ES6 modules. This would transform the original module pattern to:

import { OtherClass } from './other-class.js';

var SomeClass = function () {
this.other = new OtherClass();
};

Object.assign(SomeClass.prototype, {
someFunction: function () {}
});

export { SomeClass };

Much better!

  • No more needless calls to Object.assign to the pc namespace.
  • No further need to use the pc namespace within modules.
  • Dependencies are explicitly described in each JS file.
  • Only what is necessary is exported from modules (and the overall engine).

But what about IE11? It doesn't understand ES6 module syntax! 😱 PlayCanvas still needs to ship as a strictly ES5 library. To transform the entire codebase from ES6 module format to ES5 UMD format (PlayCanvas is used in both the browser and Node), you simply need to leverage a JavaScript bundler.

There are many options for selecting a JS bundler. In the end, 3 options were tested: Rollup, Parcel and ESBuild. You can see the PRs for each here:

In the end, Rollup was selected over Parcel and ESBuild. In testing, Parcel needed up to 16s for an initial build, while Rollup only required 3s. And we were reticent to adopt ESBuild since it was far less established and battle tested compared to Rollup. But we may review this decision in the future. Now that the engine is ported to ES6 modules, switching bundler is fairly straightforward.

With Rollup, the build script reduced from ~1000 lines to ~100 lines. Quite a saving. Rollup's plugin system made it incredibly easy to write custom handling for GLSL files and also run a C-like preprocessor in order to build debug, release and profile versions of the engine.

What's Next?

Now that we have merged the ES6 Module port, where do we go from here?

First up, Rollup is kindly informing us that circular dependencies exist in the PlayCanvas codebase.

Rollup Circular Dependencies

We want to clean things up and eliminate them. What's the motivation for that? It makes it easier for the bundler to employ tree-shaking to remove unreferenced code from the engine. At the moment, the engine's Application class imports pretty much everything. And many classes import the Application. This makes it hard to build a version of the library which doesn't include the particle engine, say. Or maybe the physics engine.

Beyond that, we are keen to explore leaving ES5 behind and fully embracing 'modern' JavaScript, or maybe TypeScript. Rollup can trivially run Babel or the TypeScript compiler as plugins, thereby ensuring we can still ship an ES5 library. We're looking forward to making that decision based on your feedback. So feel free to let us know what you think on the forum!

PlayCanvas Engine reaches 1.0.0!

· 2 min read

PlayCanvas was born 7 years ago, way back on 9th May 2011. In the early days, we were essentially prototyping, seeing what this amazing new WebGL API could do. By October 2011, we set up a source code repository and committed our first engine prototype. Right at the beginning, we adopted semantic versioning for naming our releases. Our initial commit generated engine v0.10.0. From that point onwards, we adopted a rapid release cadence, often publishing more than one release a week. The months and years passed, our team grew and feature after feature was integrated into the codebase. But through all that time, we never incremented the major version number. Why? Well, there were several reasons:

  1. Our rapid deployment meant we never delivered a monster release that seemed to warrant going to 1.0.0.

  2. We always made a huge effort to maintain backwards compatibility. Projects like the inane Doom3: Gangnam Style created in December 2011 still work fine today! So we never (intentionally) break your projects.

  3. We, uh, just never got around to it!

The semantic versioning site says:

How do I know when to release 1.0.0? If your software is being used in production, it should probably already be 1.0.0. If you have a stable API on which users have come to depend, you should be 1.0.0. If you’re worrying a lot about backwards compatibility, you should probably already be 1.0.0.

The PlayCanvas API is now very stable, mature and battle-hardened. Backwards compatibility is something we take very seriously indeed. And today, PlayCanvas is used in production by thousands of developers.

Indian Motorcycles Indian Motorcycle's PlayCanvas-powered configurator

And so, it gives me great pleasure to announce PlayCanvas Engine v1.0.0. I want to give my sincere thanks to all of the truly exceptional, hugely talented contributors who helped make this possible.

Here's to the next 7 years!

PlayCanvas Scripts 2.0

· 2 min read

We've just launched "Scripts 2.0", a complete re-design and re-implementation of the scripting system for PlayCanvas applications. Our goals were to fix an array of small irritations that had built up over using the PlayCanvas scripting for the last few years and take the opportunity to clean up the interface and simplify the creation and usage of scripts.

Here's a list of the improvements you can enjoy with the new script system:

  • rapid iteration by hot-swapping code at run-time
  • real-time collaborative code editing
  • script concatenation and minification for publishing
  • better error handling and fault tolerance
  • full folder support for script assets
  • multiple script definitions in a single file
  • simpler interface and boilerplate

Live Hot-swapping

If you choose to, you can now allow your scripts to update all running instances of your application. We dynamically reload scripts after they change. By implementing a single swap() function, you can transfer state into your new script instance and carry on as if nothing had happen. Except you've got all your new code!

Real-time Collaborative Code Editing

Now that scripts are first-class assets, we now support real-time collaboration in the Code Editor. This means you're no longer in danger overwriting other people's code. In fact, you can see it appear as they type.

To help support this, we've also improved the error handling and fault tolerance of scripts while they're running. This means bad scripts won't bring your game screeching to a halt, preventing everyone from working.

Script Concatenation

With the new script format we now support multiple script definitions in a single JavaScript file. We've added the option to concatenate and minify all your scripts into one file when you publish. This will save you many HTTP requests and reduces the size of your application, making for a much quicker start up time.

Try it Now

Scripts 2.0 is live right now and any new projects you create will have the new script system enabled. However, if you're not quite ready to move to the new system or you need some of the features that are currently only available with the old system, you can still create projects using the "Legacy Script System". Look for the option in the new project dialog.

If you haven't tried PlayCanvas before:

SIGN UP TODAY

Variance Shadow Maps for WebGL and More!

· 3 min read

May is drawing to a close and it's starting to feel like summer here in London. Let's celebrate with a PlayCanvas Dev Update! We've been busy bees, so here's a rundown of the main changes.

Variance Shadow Maps

The light component now allows you to select a shadow type. In addition to the current PCF Shadow Maps, there are new options for 8-bit, 16-bit and 32-bit Variance Shadow Maps. 8-bit VSM uses a small amount of GPU memory and is guaranteed to work on any device but is lower quality. 32-bit VSM uses a lot of GPU memory and relies on a device's ability to render to floating point textures but the quality is very good. 32-bit VSM will gracefully fall back to 16-bit and then to 8-bit should the device not provide the required capabilities.

Let's compare PCF with VSM. First, here's PCF:

shadows-sm

And here is VSM:

shadows-vsm

The big advantage of VSM is the ability to apply large blur kernels, which would be prohibitively slow with PCF. As you can see, the results are most pleasing!

VSM is still work in progress so expect more updates to land in the engine in the coming weeks.

Reworked Editor Camera Controls

We've completely rewritten the controls for the Editor camera in the 3D view. It should be far more intuitive now and also enable you to be more productive. For example, we have changed the behavior of dollying the camera to be based on what the mouse cursor is pointing at. This makes it feel much more similar to Google Maps:

zoom

Easy Asset Inspection in Dev Tools

We've made it so your assets are displayed in your browser's Dev Tools as they are in Editor's Asset Panel. This makes it much easier to locate, inspect and debug when running your game launched from the Editor.

devtoolsassets

Engine Optimizations

We've performed a thorough round of engine optimizations, aimed at speeding up your games, but also to reduce memory allocations to avoid garbage collection stalls. Specifically, we have:

  • Created a special profile build of the engine which is now only used when you run the PlayCanvas Profiler from the Editor. The regular non-profile build has the code that collects all of the timing and statistical information stripped out.
  • Optimized many commonly used functions. Here is a good example.
  • Removed many allocations that used to happen at runtime. Here is a good example.

Other Changes

  • Editor tooltips have been refactored with any missing ones added.
  • Improved reporting of an asset's references when right clicking it in the Asset Panel.

Enhanced Asset API

· 7 min read

Today we're pleased to update the engine and tools with a new Asset API. We've finessed the API to make it more intuitive and also added some extra features to make it easier for you to preload or stream in assets at any stage of your application.

This post should introduce some of the new APIs, plus give you an upgrade guide for areas of the API which have changed.

First some terms. When we talk about a "resource" we are referring to some data, usually stored in a file, that can be loaded by a PlayCanvas application. When the resource data is loaded, the engine creates a instance of some class that came from that data. e.g. the resource "image.png", is loaded to a creates an instance of a pc.Texture. The same applies for a 3D model, an animation or sound effect.

When we talk about as "asset" we are referring to a reference to a resource, with some associated data. For example a texture asset looks something like this:

{
"id": 14761,
"name": "Cerberus_G",
"type": "texture",
"preload": true,
"file": {
"url": "files/assets/14761/1/Cerberus_G.jpg",
"size": 816084,
"hash": "dc49dac4f4775191b7643b4583b3ac3f",
"filename": "Cerberus_G.jpg"
},
"data": {
"minfilter": "linear_mip_linear",
"name": "Cerberus_G",
"magfilter": "linear",
"addressu": "repeat",
"addressv": "repeat",
"anisotropy": 1
},
}

You can see the asset data for this texture as an ID, a name, a reference to the file where the resource data is, plus some additional data which isn't stored in the image file. This data is used to create the texture resource. Some assets contain lots of data (materials) some none (a text file).

Once loaded into the engine, you can use the asset registry to find assets, and you can access the loaded resource (if it is loaded) from the asset using the asset.resources property.

On to the changes:

Editor Changes

Asset Preloading

preload

The first new feature is asset preload. Previously we would load any assets that were referenced by your scene. We changed this behavior so that now assets have a specific preload property which you can enable or disable. Any asset marked as preload, and we default this to true for new assets, will be loaded during the loading screen stage and will be ready to use when your application starts. Any that are not marked as preload, will remain on the server, ready to be loaded when you need them.

We've updated existing assets to mark all existing target assets are preload. So you may need to uncheck this option on some assets if you don't actually need them.

Export and Publishing

When you publish an app or choose to download an export of your app, we now include all assets in the package. As you can choose whether or not to preload assets, this means that you can select only a subset of your assets to be loaded before your application starts. Then you can load other assets at any other stage later on. This lets you use many more assets in your games and applications but not worry about start up time. Just stream your assets in later on.

Script Loading Order

Script loading has had an overhaul, we now load scripts in parallel with other assets so load times should be reduced. We have also changed which scripts are loaded. Previously, we'd only load scripts which are referenced in scenes. We now load all scripts in your repository. Because of this we've introduced a way to set the order in which your scripts are loaded.

script-priority

Found in the menu, you can use the script loading priority dialog to choose scripts you wish to load first.

API changes

Asset Registry

The AssetRegistry object has changed slightly in the new API. The core methods are shown below. As before the AssetRegistry object is available in your scripts as app.assets.

app.assets.get(id) - get by id
app.assets.find(name, type) - search by name, return first result
app.assets.findAll(name, type) - search by name, return all
app.assets.load(asset) - load remote resource for asset

The main change here is that load() no longer accepts a list of assets and it no longer returns a promise. We're removing promise from the engine in favour of node.js style callbacks and events.

Note, we have left in a compatibility version of assets.load which accepts a list of assets and returns a promise. You should update your code to remove this as it will not be in the engine forever.

Asset Events

The asset registry (and the asset object) fire a consistent set of events which you can use to react to changes on the registry. These can be used to monitor loading progress or respond if you wish to dynamically add assets to the registry.

assets.on("add", callback) - triggered when asset added to registry
assets.on("add:{id}", callback) - triggered when asset added to registry
assets.on("add:url:{url}", callback) - triggered when asset added to registry
assets.on("remove", callback) - triggered when asset added to registry
assets.on("remove:{id}", callback) - triggered when asset added to registry
assets.on("remove:url:{url}", callback) - triggered when asset added to registry
assets.on("load", callback) - triggered on successful load
assets.on("load:{id}", callback) - triggered on successful load
assets.on("error", callback) - triggered on asset loading error
assets.on("error:{id}", callback) - triggered on asset loading error
asset.on("change", callback) - triggered when asset data changes

A good pattern for loading and using an asset is like this:

asset.ready(function (asset) {
// use asset.resource here
});
assets.load(asset);

asset.ready() will call the callback when if when the asset is loaded. If it's already loaded from before, the callback is called immediately. asset.load() does nothing if the asset is already loaded.

Resource Loader

The resource loader is a lower level interface than the asset registry. Most users won't need to access this directly as they will use the asset registry to load data. But this API has changed significantly. We've made it much simpler:

app.loader.load(url, type, callback);

I'll just leave it there, see the API docs if you need more information.

Application Scene Loading

We've added a simple API for loading new scene data via the app object

app.loadSceneHierarchy(url, callback) // load a scene file, get hierarchy, append hierarchy to app.root
app.loadSceneSettings(url, callback) // load a scene file, apply settings (lighting/physics) to current scene

These two functions accept the URL of the scene file which will be in the format "scene_id.json" e.g. "100.json".

Upgrade guide

Hopefully you'll find your application continues work as before, only now it loads faster and you have more options available to you for dynamically loading assets. However, this is a breaking API change so you may need to update your projects.

app.assets.load(asset)

If you are using this and passing in a single asset, we no longer return a promise. You should replace your code with this:

asset.ready(function (asset) {
// use asset
});
app.assets.load(asset);

app.assets.load(assets)

If you are loading a list of assets, our compatible load should still work. However, you should update your code to use the new loading format. As below

var toload = []; // list of assets
var count = 0;
toload.forEach(function (asset) {
asset.ready(function (asset) {
count++;
if (count === toload.length) {
// done
}
});
app.assets.load(asset);
});

app.loader.request()

If you were using this to make resource requests like loading Packs or asking for texture data. This is all new. You should be able to replace these calls with some other method. Maybe app.loadSceneHierarchy() or by using asset preloading to delay loading texture data. However if you really need to load a resource directly. You can use the resource loader API:

app.loader.load(url, function (err, resource) {
if (!err) {
// use resource
}
});

That's it! If you notice any problems or have trouble upgrading, get in touch on the forum.

Engine Update: Streamlining Components and Scripts

· 2 min read

With the latest engine changes released today (v0.164.0), we're streamlining our API to make it quicker and easier for you to get started with PlayCanvas. Less API to remember, more time coding your game.

Two major changes landed today. A new way to add components and replacing the old ApplicationContext object with the Application.

Adding Components

The Entity class now has addComponent and removeComponent. This makes setting up an Entity in code much easier

    var entity = new pc.Entity();
entity.addComponent("light");
entity.addComponent("camera", {
clearColor: new pc.Color(1, 0, 0);
});
app.root.addChild(entity);

You'll see that this is much less code than the previous way of doing stuff.

ApplicationContext removed

Until today, script instances would have the ApplicationContext available to them. Now we've combined the ApplicationContext and the Application.

How does this effect your code? Well, actually it doesn't. We've moved all the functionality from the ApplicationContext into Application and we now pass the pc.Application into your script. This is just reducing the API surface area.

When you create a new script. Now you'll see this as the default skeleton script:

pc.script.create('myscript', function (app) {
// Creates a new MyScript instance
var MyScript = function (entity) {
this.entity = entity;
};

MyScript.prototype = {
initialize: function () {
},

update: function (dt) {
}
};

return MyScript;
});

So, now just use app instead of context.

Anyway, that's it for this update. See you next time.

Physically Based Rendering comes to WebGL

· 2 min read

If you're working with real-time 3D, chances are that you want your scenes to look physically accurate. For many years, graphics engines have relied on a non-physical approximations without respect to energy conservation and had problems with properly decoupling lighting from the actual material properties. In recent times, huge advances have been made to formulate more accurate shading approaches as well as provide sensible material inputs, which could approximate many types of surfaces without using hacks and tweaks for each scene and lighting conditions. This is a collection of techniques and art-producing approaches often referred to as Physically Based Rendering, or PBR.

PBR in PlayCanvas

Up until now PBR has only been available in the domain of AAA console and PC gaming. Games like Watch Dogs, Assassin's Creed: Unity and Call of Duty: Advanced Warfare all feature PBR engines. Today, we're excited to announce that PBR is coming to PlayCanvas. Both web developers and game creators can now look forward to a high-level online toolset to build stunningly beautiful 3D scenes using WebGL.

shadingComparison2

Over the past 3 years since PlayCanvas started, we've seen WebGL adoption skyrocket. It's now supported in every major browser, both on mobile and the desktop. Current statistics show that 82.7% of web users have the ability to run WebGL content, and this number continues to rise. The PlayCanvas 'Star-Lord Demo' shows that WebGL is perfectly capable of implementing PBR and other high-end graphical features.

Coming Soon

Right now, it is possible for all PlayCanvas users to create this kind of content, but some of the steps need to performed in code. Our next goal is to integrate these steps directly into the toolset to allow you to build and iterate even faster.

The open source PlayCanvas engine has taken a quantum leap forwards and we couldn't be more excited to make this technology available to you. Look for more announcements about our PBR support in the coming weeks. This is just the beginning!

We'd like to give a special shout-out to Joachim Coppens who built the Star-Lord helmet fan art, and let us use it for this demo.

button

PlayCanvas goes open source

· 6 min read

When we first started PlayCanvas (over 2,716 commits ago) WebGL was just beginning to make it's way from Chrome and Firefox Nightlies into stable releases. Fast-forward to 3 years and WebGL is everywhere, Firefox and Chrome have strong support both on desktop and on mobile. And just this week the final player Apple have joined us with WebGL support for both Safari and iOS.

SWOOOP background

Today, we have some more great news for WebGL fans, game developers and web developers alike.

PlayCanvas Engine is now open source.

The entire runtime engine is available right now on GitHub under the lovely MIT license. Which means you can download it, fork it, and generally use it for anything you like.

Why open source, why now?

Ever since we started the engine open source was always on our mind. We've never hidden the source code from developers. Minified versions are available for performance reasons, but during development users always have had full access to the un-mangled engine. This is critical for debugging and fulfilling our mantra to make game development easier.

In reality the engine has been open source since the get go. Officially open sourcing the project was just a matter of time, and the time is now. The engine is mature enough that we've established the basic structure, style and functionality but contributors will still be able to make a meaningful contributions to the engine. And of course we've now found the time to lay down the foundations of the developer documentation, the API reference, the samples and all the other stuff that makes game development a joy not a chore.

For developers who just want to hack on the code with the overhead of the tools this news is great. Simply download the engine, open up your text editor and get cracking. For those of you who want more structure, and higher level tools, the PlayCanvas platform is a perfect addition to accelerate your game production.

So, this engine? What is it?

In case you haven't come across the PlayCanvas Engine before, it's a JavaScript library engineered specifically for building video games. It implements all of the major components that you need to write high quality games:

  • Graphics: model loading, per-pixel lighting, shadow mapping, post effects
  • Physics: rigid body simulation, ray casting, joints, trigger volumes, vehicles
  • Animation: keyframing, skeletal blending, skinning
  • Audio engine: 2D and 3D audio sources
  • Input devices: mouse, keyboard, touch and gamepad support
  • Entity-component system: high level game object management

Design Goals

We had a couple of goals in mind when we originally designed the engine.

  1. It had to be easy to work with.

  2. It had to be blazingly fast.

Simple Yet Powerful

As a developer, you want well documented and well architected APIs. But you also want to be able to understand what’s going on under the hood and to debug when things go wrong. For this, there’s no substitute for a carefully hand-crafted, unminified, open source codebase.

Additionally, you need great graphics, physics and audio engines. But the PlayCanvas Engine takes things a step further. It exposes a game framework that implements an entity-component system, allowing you to build the objects in your games as if they were made of Lego-like blocks of functionality. So what does this look like? Let’s check out a simple example on CodePen

playcanvas_codepen

As you can see from the Pen’s JS panel, in just over 100 lines of code, you can create, light, simulate and view interesting 3D scenes. Try forking the CodePen and change some values for yourself.

Need For Speed

To ensure we get great performance, we’ve built PlayCanvas as a hybrid of hand-written JavaScript and machine generated asm.js. The most performance critical portion of the codebase is the physics engine. This is implemented as a thin, hand-written layer that wraps Ammo.js, the Emscripten-generated JavaScript port of the open source physics engine Bullet. If you haven’t heard of Bullet before, it powers amazing AAA games like Red Dead Redemption and GTAV. So all of this power is also exposed via the PlayCanvas engine. Ammo.js executes at approximately 1.5x native code speed in recent builds of Firefox so if you think that complex physics simulation is just not practical with JavaScript, think again.

But what about the non-asm.js parts of the codebase? Performance is clearly still super-important, especially for the graphics engine. The renderer is highly optimized to sort draw calls by material and eliminate redundant WebGL calls. It has also been carefully written to avoid making dynamic allocations to head off potential stalls due to garbage collection. So the code performs brilliantly but is also lightweight and human readable.

Powering Awesome Projects

Editor

The PlayCanvas Engine is already powering some great projects. By far and away, the biggest is the PlayCanvas web site: the world’s first cloud-hosted game development platform.

For years, we’ve been frustrated with the limitations of current generation game engines. So shortly after starting work on the PlayCanvas Engine, we began designing a new breed of game development environment that would be:

  • Accessible - Using any device with a web browser, plug in a URL and instantly access simple, intuitive yet powerful tools.
  • Collaborative - See what you teammates are working on in real-time or just sit back and watch a game as it’s built live before your eyes.
  • Social - Making games is easier with the help of others. Be part of an online community of developers like you.

PlayCanvas ticks all of these boxes beautifully. But don’t take our word for it – try it for yourself and discover a better way to make games.

Speaking of Games

It's all very well talking about engines and tools, but engines are only as good as the games they let you make. Fortunately we've got a doozy for you.

SWOOOP
SWOOOP - mobile browser game built using the PlayCanvas Engine

SWOOOP is a great demonstration of what you can achieve with HTML5 and WebGL today. The game runs great in both mobile and desktop browsers and PlayCanvas also supports publishing to App Stores through third-party tools like Ludei's CocoonJS or the open source Ejecta project.

Get Involved

So you want to help us make the very best 3D engine on the web? Great! Head over to our GitHub page. Get cloning, starring and forking while it’s fresh!

Stay in the Loop

Lastly, stay in touch, we're a friendly bunch.

We’re super excited to see what the open source community will do with the PlayCanvas Engine. Get creative and be sure to let us know about your projects.

Toodle pip!

New Math API: A Transition Guide

· 3 min read

Yesterday, we announced an imminent update to the PlayCanvas Math API. It's a rare event that we introduce breaking changes and we only do it because we're certain it's going to help you be much more productive. So what have we changed?

Previously, we had a Math API which consisted of static functions that operated on arrays (JavaScript typed arrays, to be specific). It was fast - very fast - but this came at the expense of a developer-friendly interface. Therefore, we have written a brand new Math API that is object-oriented and far crisper to write against. Here's an example of how things were:

// Generate a vector from a to b rescaled to be 10 units long
var a = pc.math.vec3.create(1, 2, 3);
var b = pc.math.vec3.create(4, 5, 6);
var result = pc.math.vec3.create();
pc.math.vec3.sub(b, a, result);
pc.math.vec3.normalize(result, result);
pc.math.vec3.scale(result, 10, result);

A bit verbose! Here's how things look now:

// Generate a vector from a to b rescaled to be 10 units long
var a = new pc.Vec3(1, 2, 3);
var b = new pc.Vec3(4, 5, 6);
var result = new pc.Vec3();
result.sub2(b, a).normalize().scale(10);

Much better! As you can see, you can now chain math functions together to apply lots of operations in order.

So what if you've already written PlayCanvas script code against the old API? How do you upgrade it? Here's a brief guide.

Accessing Math Object Elements

The old way:

var x = vector[0];
var y = vector[1];
var z = vector[2];

The new way:

var x = vector.x;
var y = vector.y;
var z = vector.z;

Creating Math Objects

The old way:

var v2 = pc.math.vec2.create(1, 2);
var v3 = pc.math.vec3.create(1, 2, 3);
var v4 = pc.math.vec4.create(1, 2, 3, 4);
var m4 = pc.math.mat4.create();
var q1 = pc.math.quat.create(0, 0, 0, 1);

The new way:

var v2 = new pc.Vec2(1, 2);
var v3 = new pc.Vec3(1, 2, 3);
var v4 = new pc.Vec4(1, 2, 3, 4);
var m4 = new pc.Mat4();
var q1 = new pc.Quat(0, 0, 0, 1);

Math Object Constants

The old way:

var zeroVec = pc.math.vec3.zero;

The new way:

var zeroVec = pc.Vec3.ZERO;

API Reference Pages

We strongly urge you to check out the API reference pages for the new API. We've worked hard to ensure every function has been lovingly documented (including sample code). If you spot any mistakes, have feedback or need any help whatsoever, do let us know!

Reference pages can be found here:

Unrelated Changes

Since we have made such sweeping API changes, we have also taken the opportunity to remove some deprecated functions. The following are no longer in the engine:

  • pc.fw.RigidBodyComponent#get/setLinearVelocity - use linearVelocity property
  • pc.fw.RigidBodyComponent#get/setAngularVelocity - use angularVelocity property
  • pc.fw.RigidBodyComponent#get/setLinearFactor - use linearFactor property
  • pc.fw.RigidBodyComponent#get/setAngularFactor - use angularFactor property
  • pc.scene.Scene#get/setGlobalAmbient - use ambientLight property

We hope you like the new interface!