Release Notes 1.51.0
What’s new
Section titled “What’s new”CSS Typed Object Model
Section titled “CSS Typed Object Model”The CSS Typed Object Model is part of the Houdini APIs. It allows the manipulation of CSS styles through objects, reducing the number of strings and strings concatenations required.
This can lead to improved performance, lower memory cost and less time spent on GC, especially when used with properties requiring lots of string concatenation like transform.
We've made a partial implementation of the current draft that allows for manipulation of transform and all numeric CSS properties without using strings.
Using CSSTOM with numeric properties
Section titled “Using CSSTOM with numeric properties”Properties that can be numbers with a unit can be represented as CSSUnitValues.
After creating a CSSTOM object we can use attributeStyleMap to set the inline style of the element.
Before we would do:
element.style.left = updateValue + "px";Now with types:
unitValueObj.value = updateValue;element.attributeStyleMap.set("left", unitValueObj);But to update with types we first need to create a CSSTOM object. There are many ways to do this, for example:
Creating a CSSUnitValue
let unitValueObj = CSSStyleValue.parse("left", "50vw");// orlet unitValueObj = CSSStyleValue.parse("left", CSS.vw(50));// orlet unitValueObj = CSS.vw(50);// or if the element already has an inline style for "left"let unitValueObj = element.attributeStyleMap.get("left");Creating a CSSTransformValue
let transf = new CSSTransformValue([ new CSSScale(2,1), new CSSTranslate(CSS.px(100), CSS.px(100)), new CSSRotate(CSS.deg(5))]);// Or, since creating should happen rarely// and we will mostly reuse the same object we can use the parse functionlet transf = new CSSStyleValue.parse("transform", "scale(2,1) translate(100px, 100px) rotate(5deg)");When using CSSOM for a complex transform many strings and string concatenations could be required. Now updating a transform value can happen with 0 concatenations.
// `updateValues` contains just floats of the new values that we are going to set// `transform` is a CSSTransformValue object that is created beforehand.function UpdateFunction(updateValues) { for(let i = 0; i < attributeStyleMaps.length; i++) { // This would require 10 string concatenations if done with regular CSSOM transform[0].x.value = updateValues[i][0]; transform[0].y.value = updateValues[i][1]; transform[1].x.value = updateValues[i][2]; transform[1].y.value = updateValues[i][3]; transform[2].angle.value = updateValues[i][4]; // attrStyleMaps is an array of the attributeStyleMap for the elements // that we will be updating often attrStyleMaps[i].set("transform", transform); }}Performance gains
Section titled “Performance gains”The performance gains are most meaningful in the cases where there was a lot of strings.
For example in a test where we update the transform of 10000 elements every frame these are the results:
The JS updates are nearly five times faster!
Since in CSSTOM we can avoid making garbage there will be less GC pauses and less pressure on JS memory.
Here is the memory from the 10000 element test.
CSSTOM only uses the memory for the elements and the maps while CSSOM creates strings that keep the memory around 30% higher.
There are performance gains with properties that can be represented as CSSUnitValue as well, however the difference isn't nearly as striking. We also generally improved style setting slightly so the new version with CSSTOM is about 60% faster than before.
Supported subset
Section titled “Supported subset”The following parts of the CSSTOM draft are currently supported:
StylePropertyMap- With the following functions -set,get,delete,clear,has.CSSStyleValue.parseCSSKeywordValueCSSUnitValueCSSTransformValuewith itsCSSTransformComponentmembers:CSSTranslate,CSSScale,CSSRotate,CSSSkewX,CSSSkewY.
StylePropertyMap that is used through attributeStyleMap only works on element for inline styles, there is no support for using CSSStyleRules through CSSTOM yet.
There is a page in the documentation with the full list of supported properties tips on how to use CSSTOM in a performant way.
Custom Media Features
Section titled “Custom Media Features”We've added an easy way to control styling directly from C++/C#. This is accomplished by using custom media features like:
@media (myFeature: myValue) { div { background-color: green; }}Controlling what features are in effect is achieved by calling View::SetCustomMediaFeature(const char* featureName, const char* featureValue).
Example:
View->SetCustomMediaFeature("language", "en");To disable a feature you can do so like:
SetCustomMediaFeature("language", nullptr);The method returns a flag to indicate if the operation was successful.
For more information refer to the dedicated section for Media Queries.
Rendering
Section titled “Rendering”Support for Unity's Next Gen Graphics Context for PlayStation 5
Section titled “Support for Unity's Next Gen Graphics Context for PlayStation 5”In this release, Gameface introduces support for Unity's NGGC, Next Gen Graphics Context, which is a graphics implementation for PlayStation 5. NGGC is available on all Unity3D editor versions starting from 2021.3.21. This allows developers to switch to a graphics integration that is more performant in comparison with the only, until recently, PS5 graphics implementation on Unity.
Unreal Engine
Section titled “Unreal Engine”Concurrent Advance
Section titled “Concurrent Advance”The "Concurrent Advance" feature allows cohtml::View::Advance function calls to be executed on a worker thread, improving the overall project performance by reducing game lag instances. This is a significant advancement, as it delegates the animation updates, model synchronization, and JavaScript execution, among other things, away from the Game Thread. Note that this does not mean that different Views will be updated concurrently to one another.
Pros:
- Enhances project performance by offloading tasks to a worker thread.
- Reduces game lag by ensuring smoother operations on the Game Thread.
Cons:
- Limited interaction with View operations during Advance calls, requiring synchronization rules to avoid crashes.
- Callbacks from Gameface are executed on the worker thread, posing challenges for operations limited to the Game Thread in Unreal Engine.
- The Game Thread must wait for Advance calls to complete to maintain game-UI sync, potentially blocking the thread if
Advancecalls are lengthy. - Undefined timing of Advance calls require careful synchronization, especially when the UI depends on the game state.
This update introduces a powerful tool for developers to optimize their projects, albeit with a need for careful integration due to its operational intricacies and limitations.
Please check the Gameface Unreal Engine documentation for more details.
Migration guide
Section titled “Migration guide”CohtmlCanvasRenderer component removed from Unity3D integration
Section titled “CohtmlCanvasRenderer component removed from Unity3D integration”In the previous implementation, to render a CohtmlView into a RawImage UI component, placed within a Unity3D canvas, you had to utilize the CohtmlCanvasRenderer component. To achieve this, you had to create a game object in the scene that holds your CohtmlView and CohtmlCanvasRenderer components and another game object within the Canvas UI holding the RawImage component which we will render the UI into. We believe that this approach wasn't optimal, so we've removed the CohtmlCanvasRenderer component and modified the implementation in a way that the CohtmlView component handles everything internally.
The most significant changes that require your attention when migrating from the old approach are:
- The
CohtmlCanvasRenderercomponent is labeled as deprecated. It will be removed from the code base in one of the future releases. - The
CohtmlCanvasRenderercomponent should be removed from the scenes that use it. - All
CohtmlViewcomponents have to be placed in the same game object as yourRawImageorCameracomponents (e.g. depending if you haveInWorldorOnScreenUI).
To avoid applying these changes manually, we have implemented a script to perform this automatically when entering a scene containing CohtmlCanvasRenderer components. When such components are found, a dialog window will appear, and clicking "Yes" will delete the CohtmlCanvasRenderer component and move the CohtmlView that was used by the component. To avoid unwanted changes to the scene, you can also use the "Undo" operation in the editor. If you click "Cancel" it won't change anything on the scene.
With the new approach, when you create a CohtmlView in a Unity3D Canvas, it will create a game object with a RawImage component and automatically place the CohtmlView in that game object. Alternatively, you could also create a RawImage and add the CohtmlView component to that object.
Changelog
Section titled “Changelog”Version 1.51.0
Section titled “Version 1.51.0”| API | Removed support for Arm architecture on the Microsoft Universal Windows Platform |
| API Unity | Added a WebSocket state changed event. |
| API Unity | Added a WebSocket state changed callback |
| Feature | Added support the CSS Typed Object Model |
| Feature | Added support for custom media features |
| Feature Unity | Added support for NGGC for Sony PlayStation 5 |
| Feature Unreal Engine | Introduced a way to run update the views on a worker thread |
| Enhancement | Added support for animating |
| Enhancement | Added a warning when setting properties without units |
| Enhancement | Improved the inspector performance recording capture by allowing the selection of subsystem to be traced and a giving control over the amount of traced markers through a trace level selection |
| Enhancement Unity | Improved support for |
| Enhancement Unity | Added support for adding |
| Fix | Fixed a memory leak when animating SVG attribute values |
| Fix | Fixed a floating point precision error causing texts to wrap spuriously |
| Fix | Fixed issuing out of bounds HTTP requests for videos and added documentation about handling end of stream |
| Fix | Fixed Touch Up/End event being fired with the wrong target element in some cases |
| Fix | Fixed |
| Fix | Fixed an incorrect message about unsupported box-sizing CSS property with value border-box |
| Fix | Added a missing changelog entry for flex longhand support in version 1.48 |
| Fix | Fixed a crash when SVG elements are appended to the DOM in event handling functions |
| Fix | Fixed |
| Fix | Fixed generating wrong URLs for the views in the inspector with multiple views |
| Fix | Fixed a crash during the mouse event firing when GC collects elements that are part of the event path |
| Fix | Fixed multiple crashes and undefined behaviors related to objects being wrongly collected by GC |
| Fix | Fixed the |
| Fix | Fixed custom elements not getting upgraded when define is called after creating the element |
| Fix | Fixed an infinite recursion with |
| Fix | Fixed aliasing on the border edges of transformed elements |
| Fix | Fixed applying rules from |
| Fix | Fixed setting |
| Fix | Fixed parsing HTML comments properly with |
| Fix | Fixed |
| Fix | Fixed an uninitialized value for angle in linear gradients which was causing the comparison of two gradients to always return different |
| Fix | Fixed Player crashing on Mac OS X when allocating executable memory for V8 |
| Fix | Fixed support for Mac OS 10.12 in the samples |
| Fix | Fixed HDR sample being darker in evaluation packages |
| Fix Unity | Worked around Unity restriction to let textures be reused with different sampler states in the same frame for all graphics APIs except OpenGL |
| Fix Unity | Removing the mouse event skip logic causing lag in the Cohtml API |
| Fix Unreal Engine | Fix path rendering with |
| Fix Unreal Engine | Fix crash on Android with GLES3 in UE |
© 2026 Coherent Labs. All rights reserved.