Spaces and Shapes (May 2026 update)
Spaces, contacts, shapes and more! The May 2026 update is here, with a whole host of new features and improvements to make your games even better.
Easel is a programming language that makes your game multiplayer automatically! Intrigued? Visit our home page to learn more.
Spaces
The new Spaces feature lets you partition colliders into multiple independent physics simulations.
This lets you make a game with multiple areas, for example, a town where the player can walk around and enter different buildings. The indoor areas can be in different spaces from the outdoor area, separating their physics simulations and allowing you to even have different gravity indoors versus outdoors.
Spaces are handled efficiently by Easel's physics engine, with all the bodies, colliders, contacts, etc across all spaces still stored together in the same linear arrays and processed as one. The first level of the spatial partitioning tree is now the space, but besides that there is little overhead to having multiple spaces. The physics engine was already separately processing independent islands of bodies and this is a natural extension of that.
For this reason, it is incredibly easy to move bodies between spaces by changing the PhysicsSpace property, whereas in other physics engines this may require reconstructing the entire body and all its colliders in another physics engine instance. When your hero moves from inside to outside, it is easy to retain all their physics state and the transition is seamless.
Contacts
Sometimes, you need to know what is touching what in your game. For example, your hero can only jump when they are touching the ground. You can access information like this using the new contact query functions. See QueryContacts, QueryAnyContact and CountContacts for more details.
The BeforeCollide function has been updated to include the contact point as well. This lets you do things like spawn sparks where you hero's sword strikes an enemy.
Position Change Signals
You can now detect and respond to changes in position by awaiting the Pos and Heading properties.
For example, let's say you have a tutorial where the player must learn to walk to the right.
Instead of polling every frame, you can use await Pos to only recheck when the player actually moves, like so:
while Pos.X < 35 { await Pos }
This allows more of your world to sleep when nothing is happening, enabling better performance and larger worlds.
Per-Collider Continuous Collision Detection
Continuous collision detection (CCD) prevents fast-moving projectiles like bullets
from tunnelling through walls. It is computationally expensive, but up until this point,
CCD was an all-or-nothing setting that applied to every collider on a body.
The new intercept parameter of PolygonCollider
can enable CCD on a per-collider basis.
This is especially useful in some particular cases. For example, a hero character with two colliders:
- A small collider representing the hero's actual body, used for normal movement and collision. CCD is enabled on this collider to prevent movement artifacts.
- A large screen-sized sensor collider representing the hero's "awareness" area, used to wake up enemies when the hero is close by. This collider is so large that it could never tunnel through anything in a single simulation step. Enabling CCD on this collider achieves nothing except wastes of performance, especially because its size means it sweeps through a lot of space and therefore many other colliders every tick.
With the new intercept parameter on PolygonCollider, you can enable CCD only on the colliders where it is actually needed.
We now recommend this as the only way you enable CCD, and so are deprecating the old bullet=true parameter on Body.
Don't worry though, Easel will continue to support the bullet=true parameter so all your old code will still work.
Rhombuses
The new Rhombus shape can be used to efficiently create 2D isometric tiles in Easel.
Isometric is a great way to get some of the beauty of 3D graphics while still maintaining the performance and simplicity of 2D.
Pre-render your 3D assets into isometric sprites facing multiple directions,
then use the new Rhombus shape to give them the correct collision shape.
Stricter Networking Heartbeat
When in a multiplayer game, Easel kicks out players who have not responded to pings for 15 seconds. This is necessary as they degrade the performance of the game for everyone else, because they require everyone to maintain a longer history of the game state.
Interestingly, because WebSocket pings are built into the browser's networking stack, sometimes pings may succeed at the browser engine level while none of the game's messages are being processed. Perhaps the user switched tabs and the Easel tab was fully suspended in the background.
Easel now detects and kicks players in this situation as well, improving the experience for everyone else in the game.
Collector Defaults
Collectors are a unique but powerful feature of Easel that let you create effects like speed boosts, damage modifiers and more. Central to collectors is the concept of a merge function, which determines how all the different boosts and modifiers combine together.
If your collector is using a named merge function like FindMax or Sum, you can now
specify default values for your collectors using the ?? operator:
pub collect owner.BoostFactor ~ FindMax ?? 1
See Collectors to learn more.
Other changes
Graphics:
- The
scaleparameter on sprites now supports non-uniform scaling. Make your sprites feel more alive by giving them a little squash and stretch!
Cameras:
- When switching Cameras, smooth the initial transition using the new
acquireRateparameter. This differs fromtransitionRatewhich applies forever, even after the camera has acquired its new target.
Teams:
- The new PlayerColor property lets you manually set the color of a player or team. Now you can programmatically ensure you have a red or a blue team for all observers. See Player Colors to learn more.
- Query for players on a particular team using the new
teamparameter for QueryPlayers, CountPlayers and QueryAnyPlayer.
Shapes:
- The new
borderparameter lets you created rounded Rectangles. Rounded rectangles can be more stylish and change the personality of your game. This parameter has been added to all other shapes as well, where appropriate. - Added a new Isosceles shape.
- Equilateral now defaults to a triangle (
numPoints=3). - Position your Capsules more easily using the new
anchorparameter. - Polygons are now much more performant. The convex decomposition now uses an earcut-based algorithm more suitable for 2D rather than a voxel-based algorithm more suitable for large 3D meshes.
User Interface:
- Use the new Animate:FadeIn animation type to gently fade in a panel or other UI element.
Audio:
- The new
amplifierparameter to VolumeToggle and VolumeIntent lets you choose to control the music and sound effect volumes separately.
Language:
- Collectors now return
undefinedwhen called on an object that is nullish, rather than erroring.
couldBeNull?.BoostFactor // before - had to use null coalescing to stop the error
couldBeNull.BoostFactor // after - returns undefined instead of erroring
Thanks for reading!
Easel continues to evolve and improve, and we are excited to see what you create with these new features!
If you haven't already, check out Planetoids made by proc0, a great example of the kind of game you can make with Easel. On Easel, proc0 said "It's like Processing but for games. I really enjoyed it." We're very glad to hear that!
