oj#
oj is for getting something on screen fast, and then taking it wherever you want.
Write it in the browser on play.onejs.com with nothing installed, or in your own Unity project with the package. It is the same code either way, which is what makes the round trip work: prototype on the site, publish it so people can play it, then bring it into your project when it outgrows the sandbox.
A complete app, in one file:
import { View, Text, mount, useFrame, input } from "oj"
import { useState } from "react"
import "onejs:tailwind"
function App() {
const [n, setN] = useState(0)
useFrame(() => {
if (input.keyboard.wasKeyPressed("Space")) setN((v) => v + 1)
}, [])
return <View className="items-center justify-center w-full h-full">
<Text className="text-4xl text-white">{n}</Text>
</View>
}
mount(<App />)No root to plumb, no panel to size, no CS.*. mount knows where to render and useFrame runs before every frame with the seconds since the last one.
What you get#
| A stage | The window in logical pixels, re-rendering on resize. |
| A frame loop | useFrame, delta time, and none of the plumbing. |
| Input | Keyboard, mouse, gamepad and touch, in stage units, read when you want them. |
| Physics | A 2D world in a few lines, ticked for you. |
| Drawing | Particles, shader effects, and a vector painter that takes plain numbers. |
| Math | Vector2, Color, Mathf, seeded random, all plain JavaScript. |
Plus every component and hook you already know. Importing View from oj and from onejs-react gives you the same code.
The round trip#
Build it fast. Open the editor on play.onejs.com, or npm install ojplay in a project you already have. No panel to size, no root to plumb, no C# to write.
Publish it. A cart on the site is a URL anyone can play, with its source on the page, a leaderboard and multiplayer rooms if it wants them.
Take it to Unity. Clone the cart into Assets/, run npx ojplay init --unity, drag the prefab into a scene, and the game is running, with its source and assets. Same file, no rewrite, and from there it is an ordinary OneJS project with the whole engine behind it. A git push sends changes back to the site.
Leaderboards and rooms are the only things that want the site behind them. Elsewhere they go quiet rather than throwing.
Getting it#
OneJS 3.2.3 and later already have it; a project made before the package was renamed has it as onejs-play, which keeps working. For an older project:
npm install ojplayA project that builds with oneJSConfig (OneJS 3.9.5 and newer) resolves oj by itself once ojplay is installed. An older esbuild config needs one entry, so the bundler resolves it:
alias: {
"oj": path.resolve(process.cwd(), "node_modules/ojplay/src/index.ts"),
}and one in tsconfig.json, so the editor does too:
"paths": {
"oj": ["./node_modules/ojplay/src"]
}Both, not either. A project with only the alias builds while showing Cannot find module 'oj' on every import.
Next#
The stage and mount is the page to read first. Math and values, physics and a game's own files cover the rest.