- With no Scene view, as in a batch-mode editor, every edit-mode preview ticks unless one is selected
ProjectSetup.Initializelogs its info lines without stack tracesProjectSetup.GenerateTypingswritestypes/csharp.d.tsfrom batch mode
A world-space panel keeps running in Play Mode when its GameObject is off camera, and JS can move an element with element.transform.position. JS arrays now pass where C# takes a list.
- Play Mode ticks every JSRunner, as a build does; the overlay's Game mode applies to edit-mode previews only
element.transform.positionandscalecan be set and read from JS- A C# object JS reaches through an interface is its own proxy:
el.transform !== el - Writing
el.positionon an element fails with a message pointing atel.transform.position - Scene: Auto picks the runner whose content is closest, not its origin
- A JS array or typed array passes as a C#
List<T>(#151) - An unfocused editor starts a runner's preview without waiting for focus (#141)
- A rebuild that changes nothing no longer makes Unity reimport the bundle (onejs-unity #9)
- New projects get onejs-unity 0.11.2
C# constructors with default parameters can be called from JS without them, and generic types, extension methods and array parameters now typecheck the way they already ran. On WebGL every app's onPlay and onStop run, and useEventSync reports a C# event or property that throws instead of hiding it.
newcalls a C# constructor whose trailing parameters have defaults, with them left out (#146)- On WebGL,
onPlayandonStoprun for a strict bundle, as every scaffolded app's is (#145) - Generated types: a generic class is callable with its type arguments, as
List(Int32)(#148) - Generated types: an extension method keeps its
thisparameter on its static class (#149) - Generated types: an array parameter takes a JS array or typed array (#150)
useEventSynclogs an event accessor or getter that throws, and warns only about a missing event (#152)compute.struct's stride is the HLSL struct's size, with no rounding to 16 bytes- New projects get onejs-react 0.4.3, onejs-unity 0.11.1 and ojplay 0.12.2
Updating from 3.9.3 or earlier left the old UICartridgeEditor.cs in the project, where it no longer compiles. Updates now replace it and every other file a release renamed or removed, including in a project an earlier update already broke.
- Updating from 3.9.3 or earlier no longer leaves
UICartridgeEditor.csand five other renamed files behind - An update replaces every file a v3 release renamed or removed
Shader programs can now read what another program drew this frame, for bloom, blur and other effects in passes, and can show a low resolution as crisp pixels. An app holding a play.onejs.com cart moves to the project root with one button, and on WebGL a second JSRunner no longer breaks the first.
- Shader programs read other programs' output this frame through passes (
usePass) - ShaderEffect and ShaderProgram take
pixelatedfor hard-edged pixels at a low resolution - Move to Project Root on an app whose
~holds anoj.jsonmakes it a root cart - On WebGL, each JSRunner runs in its own realm, so a second no longer takes over the first (#140)
- On WebGL, an animation frame cancelled in the same pass no longer runs after its runner is destroyed (#142)
- An app's watcher stops when the editor quits, even after a domain reload with its scene closed (#143)
- Set Up and one-shot builds finish in an unfocused editor
- New projects get onejs-react 0.4.2 and ojplay 0.12
A player build no longer leaves the carts' files in the project, a cart runner names its cart problem before a missing Panel Settings, and OneJS builds without compiler warnings. On Unity 6.5, JSRunner's inspector says to keep the UIDocument rather than migrate it to Panel Renderer.
- A player build removes
StreamingAssets/onejs/cartsfrom the project when it ends, passed or failed - A cart runner with no Panel Settings logs a missing or duplicate cart name first
- No compiler warnings from OneJS in a player build
- On Unity 6.5+, JSRunner's inspector says not to migrate its UIDocument to Panel Renderer
A JSRunner can now run a play.onejs.com cart from its own folder at the project root, picked by name in the inspector, and apps under Assets work exactly as before. Shader programs take up to 64 uniforms and 8 textures, and choose how each texture wraps and filters.
- A JSRunner can run a root cart, linked by its
oj.jsonname - Saved scenes gain an empty
_cartline on each JSRunner, the new field's default - Shader programs take 64 uniforms and 8 textures
- A shader program can set a texture's wrap and filter, and read its size and its texels unfiltered
- New projects get onejs-unity 0.11, onejs-react 0.4.1 and ojplay 0.11
Mouse, input and transition events now fire, a project that cloned OneJS into Assets/OneJS draws its shader programs, and new projects start with Tailwind's preflight on. Programs recorded from code now live in Assets/OneJS.Recorded.sl.json, and the editor moves an existing recording there by itself.
InputBridge.GetKeysPressedlists the keys that went down this frame in the order they did- On WebGL, a second JSRunner warns that it takes over the first
- Shader programs draw in a project that cloned OneJS into
Assets/OneJS onMouseDown,onMouseUp,onMouseMove,onMouseEnter,onMouseLeave,onMouseOverandonMouseOutfireonInputfires as a TextField's text is typedonTransitionRun,onTransitionStart,onTransitionEndandonTransitionCancelfire, and bubble as in a browser- The Type Generator declares generic types under the
$Nname their subclasses extend, so inherited members are typed - A JSRunner without Panel Settings warns once in Play mode instead of doing nothing silently
- Programs recorded from code go to
Assets/OneJS.Recorded.sl.json, moved fromAssets/OneJS/on the next recording or build - New projects start with Tailwind's preflight on; existing projects keep their build config
- The Type Generator leaves test assemblies out unless asked
- The scaffold installs
onejs-react0.4, which drops the drag, tooltip and context click props that fired only in Editor windows
filter and backdrop-filter now work in USS, CSS Modules and inline styles, React updates cross to C# fewer times, and events that JS causes arrive as they would in a browser. On WebGL, a sideways wheel scrolls and event values arrive at full precision.
Migrating: a value React sets no longer fires onChange, as in React DOM, so act on the new value where you set it rather than in the handler. Run npm update in your app for onejs-react 0.3.2, onejs-unity 0.10.2 and unity-types 6000.5.3, which carry the style, text and event fixes.
- Shader effects and particles draw their first frame after leaving play mode
- A React text or style update crosses to C# once instead of up to three times
- A React class update crosses to C# once, and a text merged into its parent's text makes no element of its own
filterandbackdrop-filterwork in USS files, CSS Modules and inline styles- A style React removes falls back to the stylesheet's value instead of 0 or transparent
- On WebGL, pointer, wheel and viewport values arrive at full precision, and focus change events fire
onGeometryChangedrects arrive at full precision- On WebGL, a sideways wheel or trackpad swipe scrolls
- A shader program that reads its previous frame no longer drifts where anisotropic filtering is forced on
- An fx chain no longer softens or drifts where anisotropic filtering is forced on
- A focus or click that JS causes runs its handler at once, and microtasks wait until the JS returns
- A value React sets fires no
onChange, and a text changing never fires one - A text inside
<Text>that React reorders or Suspense hides shows once, or not at all
Closing or reloading a OneJS UI now frees everything it made, compute buffers move about five times faster, and Tailwind 2xl: classes work. A WebGL build at Medium or High stripping now renders.
Migrating: an Int32Array or Uint32Array compute buffer now reaches the shader as integers, so declare it int or uint where the shader read it as float. An integer too large for an int field now throws instead of arriving as 0, so a field that takes large values becomes a long. Run npm update in your app for onejs-react 0.3.1 and onejs-unity 0.10.1, which carry the 2xl: fix, the faster buffers and the colour fix.
- A destroyed or unassigned Unity object reads as
nullin JS - A C# exception that JS catches logs nothing; an uncaught one logs with its C# stack
- A paused shader program shows the frame drawn into its new size on WebGPU
- Compute buffers write about 5x and read about 2x faster
- An
Int32ArrayorUint32Arraycompute buffer now reaches the shader as integers, not floats: declare itintoruint - An integer past Int32 in an object from JS, such as
Date.now(), arrives whole instead of as 0 - An integer too large for an
intfield throws instead of arriving as 0 - A WebGL build with managed stripping at Medium or High renders instead of failing with "Type not found"
- Tailwind
2xl:classes apply - Closing or reloading one OneJS UI now frees its GPU buffers, shaders, input bindings, sounds and 3D scene
- Procedural colours read #fff and short hex correctly; an unreadable colour is an error instead of a wrong colour
Errors now log with their stack and open the line that threw, players ship React's production build, and 3D models load from .glb files. The API review's new names arrive beside the old ones, and a new project builds with onejs-unity build on onejs-react ^0.3.0, onejs-ui ^0.0.6, onejs-unity ^0.10.0 and ojplay ^0.10.0.
Migrating: restart the Editor after updating, since the native library changed. Copy the template's esbuild.config.mjs and build scripts, add onejs-unity/globals to tsconfig types, and delete the copied declarations from types/global.d.ts. fetch now rejects when no response arrives, so code checking status === 0 moves to try/catch. localStorage keys live under onejs: in PlayerPrefs (old keys move over on first read), so C# reading them adds the prefix. Re-enabling a JSRunner calls onStop before onPlay. Unhandled promise rejections now log as errors. The API review's new names (onejs.*, useFrame, drawing, toRGBA, open/onOpenChange, fx.useAnimation) sit beside the old ones, which keep working.
- JSRunner's Globals are declared for TypeScript in
types/jsrunner.d.ts, each with its C# type - Every public global is also under one
onejsnamespace onejs.cs.typeExistssays whether a C# type is loaded- Unhandled promise rejections log as errors on native platforms
- Errors log with their stack, and a JS error's Console entry opens its source line
- Passing the same function to a C# method twice gives the same delegate, so
RemoveListener(fn)works - A C# method call from JS crosses once instead of twice
fetchrejects with aTypeErrorwhen no response arriveslocalStoragekeeps to its ownonejs:keys;key(),lengthandclear()worklocalStoragesaves to disk a second after the last writesetImmediateyields to the next frame when an immediate reschedules itself- Re-enabling a JSRunner calls
onStopand firesReloaded - JSPad sets
__isPlayingand callsonPlayandonStop - JSPad ships React's production build and keeps the development build for Play mode in the Editor
- Image fx chains start from a texture you hold
QuickJSNative.InteropCallCountcounts JS to C# calls- 3D models from
.glbfiles through glTFast, for ojplay'suseSceneanduseModel - Models cast and receive soft shadows under a sun, sky and ground ambient, fog and point lights
- glTF materials keep metallic, roughness, normal, occlusion, emission and alpha
- Models turn on all three axes, scale after spawning and play at their own speed
- A C# static holding null reads as
nullinstead of a path proxy releaseObjectworks on any C# object- Timeouts due in the same frame run in due order
fetchsends PATCH and other methods as themselves, with their bodyHeadersandURLSearchParamsare iterable; an empty header reads as""- InputBridge reports Input System action phases, so
action.on()in onejs-unity fires - Player builds rebuild each app with
NODE_ENV=production, so players ship React's production build - An app that does not build fails the player build instead of shipping a stale bundle
- New projects build with
oneJSConfigandonejs-unity build, from onejs-unity 0.10 - New projects type the runtime's globals with
onejs-unity/globalsin tsconfig - New projects depend on
onejs-react^0.3.0,onejs-ui^0.0.6andojplay^0.10.0
UI Cartridges are now Packs, and a project made before the rename keeps working as it was. A new project's global.d.ts types fetch, URL, localStorage and the other web globals the runtime installs.
- UI Cartridges are now Packs:
Pack, the Packs tab,__pack()and~/@packs/ - A runner made before the rename keeps extracting to
~/@cartridges/ - The old names still compile and run, marked obsolete
- Breaking:
CreateInstance<UICartridge>()returns null; create aPack - Breaking: editor code reads the list as
"_packs", andPack.FilesholdsPackFileEntry - The template's
global.d.tsdeclaresfetch,URL,localStorage,AbortControllerand the other web globals the runtime installs - Existing projects: replace
types/global.d.tswith the package'sEditor/Templates/global.d.ts.txt, keeping your own additions
An npm package's art now reaches player builds, and an agent or script can set a project up with one batch-mode call, no inspector needed. A new project depends on ojplay, the new name of onejs-play, and on onejs-unity ^0.9.2.
OneJS.Editor.ProjectSetup.Initializesets a project up from-executeMethod, with no inspector- npm packages'
assets/@namespacefolders ship in player builds - A struct that holds a class, such as
FillGradient, assigns toPainter2D.fillGradientinstead of throwing - A new project depends on
ojplay^0.9.1in place ofonejs-play, and ononejs-unity^0.9.2 - The template's
global.d.tsdeclaresonejs:themes, which TypeScript 6 and newer require - Existing projects:
npm update onejs-unitybrings 0.9.2, which finds npm package assets in the Editor
Two JSRunners in one scene no longer tear down each other's particles, physics and effects, and awaiting a C# Task that already failed now rejects. A new project depends on onejs-react ^0.2.2 and onejs-ui ^0.0.5, whose popovers and menus close on a press outside them or on Escape inside a dialog.
- Reloading, disabling or destroying one JSRunner no longer disposes another's particles, physics worlds, shader effects or fx textures
- Awaiting a C# Task that already faulted or was canceled rejects instead of resolving
- A new project depends on
onejs-react^0.2.2,onejs-ui^0.0.5andonejs-play^0.8.3 - Existing projects: update
onejs-reactto^0.2.2andonejs-uito^0.0.5together;onejs-ui0.0.4 ononejs-react0.2.2 reopens a popover when its trigger is pressed
A shader program can read the frame it drew before, and count frames and the time between them, for trails, feedback and effects that settle; bump onejs-unity to ^0.9.1 for them. Existing programs draw as they did.
- Shader programs:
tex2D(previous, uv)reads the frame drawn before - Shader programs:
frameanddeltaTime ShaderEffectElement.Stepdraws exactly one frame, andFramecounts them- Shader programs: an
intuniform is typed as an int, anduintconstants past 2^31 fold correctly - A new project depends on
onejs-unity^0.9.1,onejs-react^0.2.1andonejs-play^0.8.2
Shader programs get real branches and loops, and int, uint and bool; bump onejs-unity to ^0.8.1 for them. Every shader program's hash changes once, so if you build programs in code, run the app in the editor once and commit Assets/OneJS/Recorded.sl.json before your next build.
- Shader programs:
ifis a real branch, andreturnworks anywhere - Shader programs:
while,break,continueandswitch, and loops that stop early - Shader programs:
int,uintandbool, with bit operators - Shader programs:
tex2Dlodreads one mip level - A shape's parameters and an octave count may be any value, a uniform included
- A native build stops when a recorded program is under a hash scheme no app produces, and says to run the app in the editor once
- Recording a program drops the one it replaces
- A new project depends on
onejs-unity^0.8.1,onejs-ui^0.0.4andonejs-play^0.8.1
Every shader program now draws from its compiled shader, and the old interpreter is gone. Bump onejs-unity to ^0.7.0 and onejs-react to ^0.2.0 with it.
- The shader language VM is gone: a program with no compiled shader draws nothing, and
ONEJS_SL_VMdoes nothing SLProgramBridge.UploadandCreateMaterialtake a program's hash and uniform names onlySLProgramBridge.ExistsreplacesHasNoVmShaderEffectElement.SetProgramignores its VM arguments, andSetCompileddoes nothing- A program built in code is refused past 16 uniforms or 4 textures, as a file is
- A new project depends on
onejs-unity^0.7.0,onejs-react^0.2.0andonejs-play^0.8.0
A shader program is no longer held to the old interpreter's 256 instructions and eight live values. Bump onejs-unity to ^0.6.0 and onejs-react to ^0.1.60 to lift them; a project that stays on onejs-unity 0.5 keeps working as it did.
- A shader program with no VM encoding, as onejs-sl 0.2.0 builds it, draws from its compiled shader
ShaderEffectElement.AcceptsCompiledProgramstells a host it can send oneONEJS_SL_VMdoes nothing for a project ononejs-unity0.6, whose programs carry no VM encoding- Shader programs have no length or live value limit on
onejs-unity0.6 - A new project depends on
onejs-unity^0.6.0,onejs-react^0.1.60andonejs-play^0.7.0
A shader program's noise, fbm and voronoi, and value fx.noise, look different at every seed, and now look the same on every GPU; simplex, turbulence and ridged noise don't change. A shader program with no compiled shader draws nothing instead of running on the VM, and an existing project should bump onejs-unity to ^0.5.20 so its noise on the web matches the editor.
- A native player missing a program's shader draws nothing and logs one error naming its hash, instead of running the VM
- The editor compiles a shader program the first time it draws it, and draws nothing until then instead of running the VM
- Every load of an app generates the shaders for its
.slfiles before it runs - JSPad loads
.slfiles - The shader language VM is off, and left out of every player, unless
ONEJS_SL_VMis defined - A WebGL build can no longer keep the shader language VM:
ONEJS_SL_WEB_VMis gone ShaderEffectElement.SetTimesets an effect's clock, and a paused effect draws that frame- Value noise, value fBm, voronoi and value
fx.noisedraw alike on every GPU, each in a different pattern than before - The Scaffolding list has a row for every default file the missing-file warning names, templates its list lacks included
- Restore records what it wrote, so Template newer shows when a template changes
- The Scaffolding list says Differs for a file it cannot tell you changed, instead of Modified
- A default file that differs from its template only in line endings reads Up to date
- Edit-mode preview and Initialize Project name the default files that are missing
- A new project depends on
onejs-unity^0.5.20 - Existing projects should bump
onejs-unityto^0.5.20, or shader programs' noise draws the old pattern on WebGL
A default file you delete from a project now stays deleted, and the inspector's lists remove the entry you clicked after an undo. A horizontal slider stays centred beside its label when its height is restyled.
- Default files are scaffolded once, so a deleted one stays deleted and the Scaffolding list drops its X; Restore brings one back
- The first Play after upgrading writes, once, any default file a project never had, including one removed with 3.5.0's X
- The Stylesheets, Preloads, Globals and Cartridges lists' X button removes the entry clicked after an undo, instead of another
- A horizontal slider's track stays centred when its height is restyled
Shader programs now run as real compiled shaders in every player, native and WebGL, instead of on an interpreter. Bump onejs-react and onejs-unity in an existing project, or its shader programs will not draw in a WebGL build, and commit Assets/OneJS/Recorded.sl.json if you build programs in code.
- Native players draw shader language programs compiled instead of on the VM
- A WebGL build of a Package Manager install no longer fails at start with a stripped type
- A program with no compiled shader in a native player falls back to the VM and warns once, naming its hash
- Programs built in code are recorded into
Assets/OneJS/Recorded.sl.json, which a project commits - Shader language programs run compiled on WebGL2 and WebGPU, and the VM no longer runs them in a WebGL player
- A program's
resolution,fragCoordandaspectread the element's real size - Shader effects draw the right way up on WebGL2
- A program texture with nothing bound reads white on every backend
- WebGL builds leave out the shader language VM
- A shader program that needs a newer VM is refused with a message instead of drawn wrong
sdftakes the fifth and sixth parameters of orientedVesica, roundedBox, orientedBox, triangle, horseshoe and bezier- A scalar or
float2toLinearin a shader program draws the same in the editor as in a player toLinearin a shader program runs at full precision on mobile- A shader program can assign to a swizzle, and a single number fills a vector
- A shader program can no longer name a value after a keyword or a type
- A new project depends on
onejs-react^0.1.59andonejs-unity^0.5.16 - A file can be removed from JSRunner's Scaffolding list, so Play mode stops recreating it
- Existing projects must bump
onejs-reactto^0.1.59andonejs-unityto^0.5.16, or shader programs do not draw in a WebGL build
Dialogs and drawers now keep keyboard focus inside them, and preventDefault() in pointer and key handlers now works as it does in a browser, so check any handler that already calls it. New projects start on onejs-play 0.6; older ones stay on their pin until you change it.
onFocusInandonFocusOutfire, and bubble to ancestorsFocusScope's focus trap works, soDialogandDrawernow hold focuspreventDefault()on pointerdown keeps focus where it waspreventDefault()works in key handlers; aTextFieldno longer receives a key itsonKeyDownprevents, Enter included- Two pointer events within one millisecond both reach JS, instead of the second being dropped
- A new project depends on
onejs-play^0.6.1 - Older projects can bump
onejs-playfrom^0.5.5or^0.1.1to^0.6.1, which builds each physics world once, not twice onejs-play0.6 removes the stage fits:useStage()returns only{ width, height }
OneJS no longer installs Unity's Input System into every project. If you set up a project on 3.4.5 or 3.4.6 and use the Input System, add "com.unity.inputsystem": "1.19.0" to Packages/manifest.json when you upgrade.
- OneJS no longer installs the Input System;
InputBridgeneedscom.unity.inputsystemin the project - A project without the Input System package compiles, whatever its input handling setting
preventDefault()works in navigation handlers, and keeps focus in place on a move
With two OneJS apps live at once, an await could hang forever and log nothing about it. A 2D physics world also stops printing a warning per body, and a body's density finally sets its mass.
- An async C# call resolves in the runner that made it, not whichever ticks first
- A runner's task backlog no longer delays another runner's completions
QuickJSNative.RegisterTasktakes the owning context- A physics world builds without warnings, instead of a line per body
- A body's density sets its mass, instead of being ignored
- Generated
CS.*typings hand back the type you passed, soGetComponent(MeshRenderer)is a MeshRenderer
npm install failed in every newly scaffolded app, so Initialize Project left new projects with no dependencies and no bundle. The scaffold pinned an onejs-unity version that no published onejs-play can pair with. OneJS also now installs the Input System it has always required.
- A new app's
npm installresolves, instead of failing on theonejs-unityandonejs-playpins com.unity.inputsysteminstalls with OneJS, which its runtime assembly already referenced- A build processes the scenes it was given, not the Build Settings list
- A build that ships the open scene gives that app its bundle, instead of none
A player build now finds every OneJS app, including one that ships inside a prefab through Addressables, a Resources/ folder or a plain reference; before this such an app shipped with no bundle and ran OneJS's placeholder instead. Two smaller fixes: JSRunner leaves a UIDocument you added yourself alone, and Initialize Project says why it did nothing rather than reporting success.
- Every JSRunner in a scene or a prefab is built, so an app that ships through Addressables, Resources or a prefab reference gets its bundle and assets
Exclude From Buildon JSRunner leaves a runner out of the build, and out of the asset collision check with it- An asset path claimed by two apps warns instead of failing the build when a prefab reached either of them
- Every runner sharing an app gets its bundle, instead of only the first
- Clearing Panel Settings removes only a UIDocument that JSRunner added itself
- Initialize Project warns and names the folder instead of reporting success it did not deliver
In a project with more than one OneJS app, a build kept only the last app's assets and silently dropped the rest; that is fixed, and two apps claiming the same asset path now fail the build instead of overwriting each other. The rest is about saying what went wrong: a failed C# call on WebGL throws with the reason, and the type generator writes real array types instead of any.
- Every app's assets reach a multi-app build, instead of only the last one's
- A build fails when two apps ship the same asset path, naming both
- The type generator emits real array types instead of
any, andSystem.TypeLikefor aTypeparameter - A failed C# call throws with the reason on WebGL, where it returned
nulland said nothing - The thrown error names the missing type or member instead of "C# invoke error"
Fixes two Unity 6000.5 bugs: a ScrollView ignored its scroll settings, and styling a TextField's input could stop the whole UI from appearing. The rest is the .sl shader language: shaders written beside the game, running in the editor while you edit them and compiled for a build.
- Nested C# types resolve by their dotted path:
CS.UnityEngine.UIElements.ScrollView.TouchScrollBehavior.Elastic - A CS path that names no type warns when used as a value instead of reading as 0
- A static call skips generic overloads it cannot invoke;
UQueryExtensions.Qthrough the class works on Unity 6000.5 interop.bindrefuses a generic overload at bind time instead of throwing on every callinterop.bindresolves a type by the same rules as the rest of the API, nested types included<ScrollView touchScrollBehavior>andnestedInteractionKindset the value named (onejs-react 0.1.53)<TextField inputStyle>andinputClassNameno longer throw during mount on Unity 6000.5 (onejs-react 0.1.53)- Native fetch works when the C# request completes at once, as it does for small Android StreamingAssets files
- A
float4of literals is one instruction and one register, not five and four (onejs-unity 0.5.12) sl.rampbuilds each stop as it needs it; a four stop ramp costs 4 registers, not 7 (onejs-unity 0.5.12)- A program's textures bind by the name the shader declares (onejs-react 0.1.52, onejs-unity 0.5.12)
- A
.slimport can hand over the file's own text, for showing a shader beside what it draws (onejs-unity 0.5.12) - The Play editor reads
.slfiles: highlighting, errors as you type, completion and hover, from the parser itself - An ejected game's
.slfiles highlight as HLSL in VS Code with nothing installed slprograms readresolution,fragCoordandaspectfrom the element, not the game window (onejs-unity 0.5.12).slfiles: a shader program in HLSL text, parsing to the program theslEDSL records (onejs-unity 0.5.12)import plasma from "./plasma.sl": encoded at build time, with a.d.tsand a shader manifest beside the bundle (onejs-unity 0.5.12)- An ejected Play game compiles its shaders from the first frame (onejs-play 0.5.2)
- A uniform's declared default reaches the interpreter, not just the compiled shader (onejs-react 0.1.52, onejs-unity 0.5.12)
<ShaderProgram>checks uniform names against the program it was given (onejs-react 0.1.52)sl.cross,sl.reflectandsl.remapadded (onejs-unity 0.5.12)slselect, lerp, step, smoothstep and clamp take their width from the widest operand (onejs-unity 0.5.12)- Shader programs interpreted in the editor are recorded and compiled on the next tick; an ejected game runs compiled from its second frame with no manifest written by hand (onejs-unity 0.5.11, onejs-react 0.1.51)
- Generated shaders copy every include SLCommon reaches, so they no longer compile to magenta since noise landed
- A
Colorread from C# hasr,g,bandain JS, on every path - A zero-alloc binding can return a string, a data struct or an object; native libraries rebuilt
fxcolours are sRGB as written; gradients and ramps interpolate in sRGB and convert to linear (onejs-unity 0.5.7)fxnoisetype: "turbulence"is real turbulence (sum of absolute octaves) and"ridged"is new (onejs-unity 0.5.9)slnoise shares fx's fields:sl.simplexis real simplex,sl.fbmtakes a base,sl.turbulenceandsl.ridgedadded (onejs-unity 0.5.10)sl.rampmixes its stops in sRGB and converts once;sl.colorandsl.toLinearadded, with aTO_LINEARopcode in both backends (onejs-unity 0.5.8)- Pointer and mouse events carry
localX/localY, relative to the element the handler is on backgroundImageand thefxand asset hooks share an opaqueTexturetype instead ofunknown(onejs-react 0.1.48, onejs-unity 0.5.1)fx.useAnimatedTexturedraws with the latest render's build function each frame (onejs-unity 0.5.1)fxramps and gradients take hex strings, bare colour lists and readonly arrays (onejs-unity 0.5.2)fxnoise takesscroll, panned by the animated build's clock (onejs-unity 0.5.2)fx.useImagebuilds synchronously and never returns null (onejs-unity 0.5.2)fx:threshold(low, high), gradient directions by word, aturbulencenoise preset, andalphaon a stop (onejs-unity 0.5.5)fx.canvas(size)bakes the size into the sources;useAnimatedTexturetakes one (onejs-unity 0.5.6)- Physics bodies are handles:
world.bodies[i].enabled,moveTo,setVelocity,push(onejs-unity 0.5.6) Paintercolours take a hex string, andcircle(x, y, r)joins the path methods (onejs-react 0.1.50)Slidertakesminandmax(onejs-react 0.1.50)- Particle emitters read
glow,spinandposition; the old names remain (onejs-react 0.1.50) - oj's
audio.loadtakes a file name like the texture loaders (onejs-play 0.4.5) - A non-zero
letterSpacingswitches the element to the Standard text generator, so a content-sized spaced line no longer wraps its last glyph - The
eggshape takesh,r,rTopandbulge, Quilez's four parameter egg, infx,sland TextureFX ShaderProgramwarns once about a uniform name the program never declared (onejs-react 0.1.48)ScreenProvidertakes asizeso a host can drive breakpoints from its own box (onejs-react 0.1.48)InputBridge.GetKeyDown/GetKeyDownByIdare deprecated forGetKeyHeld/GetKeyHeldById; the old names keep their behavior and warn- TextField:
inputClassNameandinputStylestyle the inner input (onejs-react 0.1.46) - Tailwind: opt-in
preflightstrips the runtime theme's control chrome (onejs-unity 0.3.1) - The build validation test assembly no longer ships in player builds
- An unknown style key warns once instead of being dropped silently
- A USS declaration UI Toolkit will ignore logs a warning naming it and its line
- AI Skills ship at
AI/Skills/, discovered by Unity's AI Assistant - Tools > OneJS > Install AI Skills copies them where terminal agents look
- An image that downloads but Unity cannot decode says so, instead of a generic failure
- WebGL: trackpad scrolling advances every frame instead of lurching every few
- WebGL: a small trackpad nudge scrolls instead of doing nothing
- WebGL:
globalThis.__ojWheelNotchtunes wheel granularity at runtime; a ScrollView's step follows it
fx: a GPU image pipeline with noise, gradients, 42 signed distance shapes, color adjustments, 27 blend modes, spatial moves and neighbour filtersfx: a whole chain crosses to C# once, and its per-pixel steps fuse into one blitfx: a chain can render into a target the caller keeps, for animationconsole.warnandconsole.errorlog at Unity's warning and error levels instead of all arriving asDebug.Log- A JS
Errorkeeps its message when it is logged - Synthetic events are built only when a handler asks for one
- WebGL: trackpad scrolling covers the same distance as a mouse wheel instead of many times more
- Tailwind: utility rules emit in the web's cascade order instead of file scan order
- Tailwind:
flexsets row,blocksets column - Tailwind:
flex-1includesflex-basis: 0 - Structs: read-only properties are visible from JS
- Structs: a property and a field that differ only by case are both kept
- Structs: a property that throws no longer loses the rest of the struct
- macOS: the native library is a universal binary, so Intel slices of Universal player builds no longer fail to load
- macOS: the library targets macOS 11.0 instead of whichever SDK built it
- New projects scaffold with
ojavailable: theonejs-playdependency, the esbuild alias and the tsconfig path
- Windows: the native library no longer imports libwinpthread-1.dll, which broke every 3.2.0/3.2.1 Windows project with
DllNotFoundException: quickjs_unity - CI verifies every shipped native plugin depends only on OS-provided libraries
- 2D physics:
PhysicsWorld2Druns a C#-owned rigidbody world for UI elements - Audio:
AudioBridgeplays clips through Unity instead of WebAudio - The Input System package is now optional;
InputBridgecompiles only when it is installed - The package declares the engine modules it needs
- WebGL: particles, physics and shader effects tick in builds
- WebGL: completed C# Tasks settle their JS promises, so
audio.loadand remote<Image src>resolve PhysicsWorld2D.SetPositionmoves a body that is not simulatingProc/MeshGeneratorcompiles into the runtime assembly
GetJSFunction<TDelegate>()on JSRunner, QuickJSUIBridge, and QuickJSContext binds a named JS function to a typed C# delegate- JS functions assigned to C#
Funcdelegates now marshal their return values (all arities up to 4) JSRunner.Reloadedevent fires after each hot reload- Callback handles are generation-tagged; a handle from a destroyed context fails loudly instead of invoking the wrong function
- JS arrays returned to C# marshal as arrays instead of null
- Native library and C# runtime verify a shared ABI version at startup
- Fixed native buffer leaks and a Windows allocator mismatch in callback result marshaling
- WebGL: scheduler clock seeds from
performance.now(), so timers created during boot fire at their real due times - WebGL: a re-evaluated bootstrap retires the previous generation's timers and always captures the true browser natives
- WebGL: context teardown is refcounted and leaves the page pristine when nothing was migrated
clearTimeout/clearIntervalfall through to the browser for timers created before OneJS booted
- WebGL:
unityInstance.Quit()no longer hangs the page; teardown returns captured timers to the browser - WebGL: JS to C# calls after context destruction are ignored
- Zero-delay timeout chains and interval backlogs no longer stall a frame
- Cartridges extract as soon as they are assigned; the Cartridges tab warns when
onejs-uiis missing from package.json import "onejs:themes"registers every extracted cartridge theme (onejs-unity 0.2.19, wired in scaffolded configs)
- Added
AbortController/AbortSignalpolyfills (fetchdoes not observe signals yet) - Extension methods now accept omitted trailing optional arguments (
element.Q(name)works)
- Added
TreeViewBridge, pairing with onejs-react 0.1.43's<TreeView>component and ListView selection fixes - Cartridges can declare a version; the Cartridges tab flags outdated extractions
- New projects scaffold with
onejs-uiin package.json
- Fixed legacy Input Manager compile break: FastPath's
UnityEngine.Inputregistrations resolved against the newOneJS.Inputnamespace in projects with the legacy input manager enabled - Added GitHub CI: EditMode + PlayMode suites on every push and PR
- Replaced Puerts with a purpose-built QuickJS integration: no third-party engine layer, smaller footprint, works everywhere JIT is prohibited, including iOS
- WebGL builds now run on the browser's own JS engine (V8/SpiderMonkey) for full JIT performance
- React 19 is the core UI model: a custom reconciler renders JSX directly to UI Toolkit elements, no DOM, no webview
- New
JSRunnercomponent replaces ScriptEngine: PanelSettings as the project marker, one-click Initialize Project scaffolding - Edit-mode preview: your React UI renders in the Game view without ever entering Play mode
- Hot reload in both edit and play mode, with
onPlay/onStoplifecycle hooks and automatic cleanup of JS-created objects JSPad: a second MonoBehaviour with an inline code editor for instant prototyping, no project setup- Built-in Tailwind-style JIT utility generator and CSS Modules, both embedded in the bundle (no external dependencies)
- ES6 imports of C# namespaces:
import { Vector3 } from "UnityEngine" - Zero-alloc C# interop: FastPath accessors, pre-registered bindings, batched style and vector-drawing commands
- 2D particle engine and GPU compute bridge rendering inside UI Toolkit elements
- Web APIs out of the box:
fetch,WebSocket,localStorage,URL, base64, timers UICartridgecontent packs: drop a single asset onto a JSRunner to install themes and effectsonejs-ui: a themeable React component library with premade themes (Pixel, Kawaii, Sketch)- AI-native development via the Unity MCP Server companion package
- Scene Folder workflow: each app lives next to its scene in a git-friendly folder, tilde-suffixed so Unity ignores sources
- The editor manages the esbuild watcher automatically: save a file, the UI hot-reloads
unity-typesnpm package ships generated TypeScript definitions for the wholeCS.*surface- The full JS side verifies from the CLI (
npm run build/typecheck), no editor needed
- All core types now live under the
OneJSnamespace (with backward-compatible resolution for older bundles) - Built-in stability monitoring: handle-table and async-task-queue leak detection with automatic warnings
- Player builds embed the JS bundle automatically, nothing passes through StreamingAssets
- Added Android 16KB page size alignment support
- Fixed WebGL libpuerts.a meta file
- Updated Linux (x86_64) libpuerts.so
- Fixed memory leaks in
Resource(added caching for images, fonts, and font definitions) - Fixed
Document.clearCache()not destroying cachedTexture2Dobjects (GPU memory leak) - CoroutineUtil Instance fix
- WebGL PuerTS tweak for Unity 6.3 (robust WASM table lookup,
updateMemoryViewshook)
- Make Sample code to use "PhysicMaterial" for pre Unity 6 versions
- Guard Coroutine Eval in Runner
- Fixed ExCSS.Unity issue on Unity 2022.3
- Fixed WebGL Playmode issue with
documentnot being set
- Fixed regressions in Unity 6.3 Runtime USS where UnityEditor namespaces were still referenced in runtime code.
SVG support and uss filters are now built-in!
- Runtime USS rework for Unity 6.3 compat
- Sample Scene updated for Unity 6.3 (added svg loading and filter usage)
- Improved float parsing in DomStyle (culture-agnostic)
- Puerts filepath handling with spaces
- CI Mac shell fix
- Added ScriptEngine.Refresh()
- More webgl build tweaks
- Tighter GetLength() in DomStyle
- SimpleGrid bugfix
- Game UIs CI test
- DomStyle caching
- CultureInfo.InvariantCulture for Length parsing
- EditorScriptEngine updates
- Added tick Error handling event to ScriptEngine and EngineHost
- Delayed EvalFile(). This ensures the inital mounting happens after the initial UIDocument load (so that the initial layouts are already calculated).
- Added an extra ".root" css specificity to generated TW classes.
Improved some workflows to support the rollout of our game UIs.
To upgrade from a previous version:
- make sure to update
onejs-coreandonejs-preactto^2.0.0 - The following defaults have changed:
postcss.config.js,tailwind.config.js,tsconfig.jsoninput.css,.vscode/tasks.json
- You can delete them and run scene with ScriptEngine again (be mindful if you have custom changes)
To install OneJS's Game UIs, you can now run:
```bash
npx oj add all
```
This will work as long as you have a premade-uis.tgz(.bytes) file anywhere in your Assets/ folder. This file is only included in the OneJS Asset Store package.
- Debugger Support options on ScriptEngine
- WebApi to support headers
2xl -> xxlso we don't run into char escaping issues
onejs/math is now available! See onejs-core repo for more info.
- Better custom UIElement Events handling
- Normalized Path in ScriptEngine.GetFullPath()
- EngineHost.subscribe() improvements
- Better uss class name escaping
- Many Editor UI improvements
- Many updates on the npm modules (onejs-core, onejs-preact, onejs-comps, etc)
- Backends MenuItems
- Removed BaseEditor override
- Bundler rewrite
- DTSGen improvements
- 2021.3 compatibility
- Fixed puerts reimporting issue
- Various EditorScriptEngine improvements
- Use "Assembly-CSharp" by default for DTSGenerator
- EditorEngineHost refactor
- Codegen: accomodate for Nullable types
- EngineHost Refactor
- Added a global.d.ts by default
We’re releasing this now, ahead of the Editor UI update (expected in a couple of weeks), as it includes significant improvements and bug fixes that are worth rolling out early.
If you are updating an existing project, make sure to also bump the onejs-core package to ^1.0.6 in your package.json.
- Added WebApi from V1
requestAnimationFrame()bugfix (Thx @Kodra)DomStyle.GetLength()bugfix- Use min/max for gradientrect
- Added support for global namespace in DTSGenerator
onejs-coredependency bumped to^1.0.6- Many more bugfixes and improvements in
onejs-coreandonejs-preact
(Most of the Editor UI code are actually in. However, we'll use the next release to get into the details.)
-
Switched from Jint to Puerts as the JavaScript engine
- Provides 3 backends: QuickJS, V8, and NodeJS
- Significantly improved performance (20x to 100x faster)
- Better memory management with static wrappers and blittable optimizations
-
Adopted ESBuild workflow
- Bundles everything into a single file for easier deployment
- Automatic handling of node modules
- Experimental support for Custom Editor/Inspector UI
- Support for node modules and npm packages
- Improved TypeScript definition generation
- Experimental Custom Editor UI support
- Quick backend switching with
npm run switch - Enhanced interoperability between C# and JavaScript
- Updated ScriptEngine component with new interop settings
- Streamlined global variable exposure from C# to JavaScript
- Improved overall stability and performance
- Updated Preact to 10.21
- CultureInfo.InvariantCulture fix for HexMatchToRgba()
- Add AddRuntime* APIs for ScriptEngine
OneJS V2 is coming! Get in our Discord server and private repo to follow the progress.
- Changed ScriptEngine's LateUpdate() to Update() to fix Task resolution error
- DPIAdjuster improvements
- Added checkEquality option to EventfulPropertyAttribute
- Exposed EngineHost on ScriptEngine
- Tailwind 4-comp hex color fix
- ScriptEngine OnEnable & OnDisable support
- useCapture support for addEventListener and removeEventListener
- Global host and interop objects with event subscription function (#12)
- Improved CommonJS path resolver (#11)
- Cyclic error fix for preact falsey check in Hookstate
- TSDefConverter moved to using UI Toolkit instead of IMGUI (credit to @iDevelopThings)
- Various Jint tweaks (RunAvailableContinuations & UnwrapIfPromise)
- Updated Jint with rest/spread bug fix
- Fixed the # char bug for TW classes
- Added _includeOverriddenMembers for TSDefConverter
- Fixed OpenDir for Linux
- Auto-reimport uss after generation (Tailwind)
- useEventfulState() forceUpdate() regression fix
- Updated Jint to [beta-2050]
- jsx-runtime support
- OnPreprocessBuild now accommodates when there's no scene listed in the build settings
- Added comps sample scene
- Added GradientTextureFill Job example
- Added onEngineDestroy
- Added webapi.getImage()
- Added OnInitOptions to ScriptEngine
- Dom.addEventListener now go through all loaded assemblies
- Fixed regression in InitAllUIElementEvents()
- Added TagTypeResolver to ScriptEngine
- JSON module import
- Added default tasks.json for vscode
- Added EventfulPropertyAttribute and corresponding source generator
- Added ValueTuple check in TSDefConverter
- Added a new Component Library under ScriptLib/onejs/comps. These are inspired by HeadlessUI.
- Please see the v1.6 Docs for more information.
- ScriptLib folder now will contain the .ts files. This is to make it easier to refer to the TS implementation instead of the compiled JS.
- Support for Tailwind compiler has landed!
- Documentation here: https://onejs.com/docs/v1.6/tailwind
-
Added more CLR exception handling logging
-
VisualElementExts ForceUpdate()
-
Preact <-> Jint Cyclic ref error fix
-
Added array type mapping for TSDefConverter
-
Added public properties for ScriptEngine option fields
-
Added _logRedundantErrors to ScriptEngine
-
BuildProcessor bugfix for Cloudbuild @mattehr
-
Improved addEventListener and removeEventListener to allow multiple callbacks on the same event
-
Jint Engine tweak: MemberNameComparer = StringComparer.Ordinal
-
Color processor fix
-
More fields added to Image tag (jsx def)
-
Added unitySliceScale support (new in Unity 2022.2)
-
[StyleProcessor] Check for all falsy values instead of just null
-
forceUpdate() in useEventfulState
-
Added ref support for styled comp
-
Added memo to preact/compat
- Better VectorAPI version check
- .boxedValue alternative (for Unity 2021.3)
- Auto-create directory for player workingDir
Online documentation was revamped! Check it out at https://onejs.com/ There is now a new comprehensive Tutorial101.
- Cloud Build support (some internal changes to Bundler)
- Runtime USS errors are now properly handled (No longer need to reload scene)
- Offline Doumentation.pdf revamped
- Many minior tweaks and bugfixes
- New custom Editors for ScriptEngine, Bundler, and LiveReload. Removed dependency on NaughtyAttributes.
- Some internal changes done to support the launch of VanillaBox
- Removed lib.dom.d.ts from the default Typescript typings
- Made WorkingDir more configurable per ScriptEngine. This also makes having multiple ScriptEngines easier.
- Replaced FrontLoader and ImageLoader with the
resourceglobal variable - Moved OneJSBuildProcessor functionality to Bundler
- Removed
Extract ScriptLib On Startoption as this is replaced by the ScriptsBundle
- TSDefConverter now supports Jint syntax for events ("add_" and "remove_").
- Added a new Sample (CharManSample)
- Bugfix for
clearInterval()not working inside the queued action classnamesadded- VectorAPI check for sample scene
- Implemented
onejs/styledwhich includes both styled-components and emotion APIs. backgroundImageStyle prop now also accepts Sprite objects in addition to string paths and Texture objects.- Reverted default Trickledown.
- ScriptEngine.Objects list will now accept any UnityEngine.Object, not just MonoBehaviours.
- Implemented useEventfulState()
- Fixed inconsistent timing between performance.now() and requestAnimationFrame()
- Keep existing unity-* classnames intact for stock controls
- Added IsByRef check in TSDef Converter
- Updated Preact Signals to latest version
- Path Resolver tweak
- Added user-defined sub-directories for the bundler to ignore during runtime updates
-
Async/await are now supported in OneJS scripts
-
Preact Signals are also now fully supported
-
Changed QueuedActions to use PriorityQueue
-
Added RadioButton and RadioButtonGroup TS Defs and sample usage
-
Fixed issue with relative path loading same modules more than once
-
Fixed OneJSBuildProcessor+OnPreprocessBuild _ignoreList issue
-
NetSync: Have Server also Broadcast
-
Tailwind ParseColor bugfix @LordXyroz
- Patched ExCSS.Unity.dll so it doesn't cause conflicts with other Unity packages
- Fixed turning Live Reload off for Standalone builds
- Add Navigation Events to the TS definitions
- Better UglifyJS error handling
- Adds support for chaining pseudo selectors @Walrusking16
- Tag lookup fix, Dom compliance and ListView example @Sciumo
You are now able to load CSS strings at runtime via document.addRuntimeCSS(). See https://onejs.com/runtimecss for
more information.
- Runtime CSS
- Updated Jint to latest
- Copy to Clipboard for TSDefConverter (credit to @Sciumo)
- Added node_modules to JSPathResolver
- _engine.ResetConstraints() in Update Loop
- Action queues without coroutines
- setInterval
- Implemented onValueChanged for UI Toolkit controls
- Fixed __listeners Linux slowdown
- GameObject Extensions AddComp(), GetComp(), and FindType() fixes
- UIElementsNativeModule handling for 2022.2 and later
You are now able to keep all your scripts under {ProjectDir}/OneJS. And the scripts will be automatically bundled
into{persistentDataPath}/OneJS for Standalone builds.
- Added a Bundler component that is responsible for extracting scripts.
- Added OneJSBuildProcessor ScriptableObject that is responsible for packaging scripts (for Standalone builds).
- This is generally automatic as it uses OnPreprocessBuild
- It also provides glob ignore patterns for things you don't want to include in the bundle.
- Added
[DefaultExecutionOrder]for various components. - Added an extra option (
Poll Standalone Screen) on the Tailwind component to allow you to also watch for screen changes for standalone builds.
- Fixed various preact cyclic reference errors
- Fixed preact diff bug (missing parentNode)
- Fixed Tailwind StyleScale regression in 2021.3
- Flipbook Visual Element
- Negative value support for Tailwind
- Opacity bugfix
- Preact useContext bugfix
- Preact nested children bugfix
- Tailwind
- Multi-Device Live Reload
- USS transition support in JSX
- Completely reworked Live Reload's File watching mechanism to conserve more CPU cycles. Previously it was using FileSystemWatcher (poor performance when watching directories recursively).
- New GradientRect control (allows linear gradients with 4 corners, demo'ed in the fortnite ui sample)
- Fixed Double to Single casting error during Dom.setAttribute
- Fixed object[] casting during Dom.setAttribute
- Fixed unityTextAlign style Enum bug
- Fixed overflow style Enum bug
- Fixed a bunch of setStyleList bugs
- Full Preact Integration with 1-to-1 interop with UI Toolkit
- Live Reload
- C# to TS Def converter