Opening in Unity
Add a cart to a Unity project
The download button on a cart. Needs a Unity project (6.3 or newer) with OneJS installed from the Package Manager: https://github.com/Singtaa/OneJS.git
At the project's root, where Assets and ProjectSettings are:
npx ojplay add @<handle>/<name>That is the line under the download button. It puts the cart in Assets/<Name>/~, installs and builds it, and puts it in a scene: your first build scene, or a new Assets/Scenes/Main.unity. Open that scene and press Play.
With the project open in Unity, it leaves your scenes alone and says which prefab to drag in.
| Your own cart | Lands as a git clone. Edit, save, git push: the site builds it |
| Somebody else's | Lands as the build they published. To change it, fork it on the site and add yours |
| Private cart | npx ojplay login first, once per machine |
| A piece of an app you have | Run the line in that app's ~ folder instead. oj.json lists the cart, and import { Bolt } from "@<handle>/<name>" works; its art ships with your build |
Your cart file does not change.
What it writes
Assets/<Name>/<Name>.prefab |
A JSRunner: the thing placed in the scene |
Assets/Scenes/Main.unity |
Only when the build list has no scene, and then added to it |
Assets/<Name>/PanelSettings.asset |
Marks the folder as the project |
Assets/<Name>/app.js.txt |
The built cart |
~/package.json, tsconfig.json, esbuild.config.mjs, ... |
OneJS's own build, from the OneJS you installed |
~/assets/ |
Copies of your files, refreshed on every build |
Everything inside ~ that is not the cart is kept out of git, so git status shows only your cart. Unity ignores a folder named ~.
By hand, the same thing: git clone https://play.onejs.com/@<handle>/<name>.git "Assets/<Name>/~" (or git submodule add in a project that is a git repository), then npx ojplay init --unity in that folder.
Input
input needs the Input System package, with Active Input Handling set to Input System or Both. New Unity 6 projects have it. Without it: one warning, and input stays idle.
Positions from Input System actions are in screen space. input.mouse and input.touches are converted for you.
What changes
| In Unity | |
|---|---|
assetUrl |
~/assets/, or StreamingAssets in a build |
mount() |
Starts its own runtime |
A .sl shader |
Becomes a real shader, compiled by Unity |
| The control theme | Comes with you |
What you gain: your own C#, all of Unity, scenes, 3D, every build target, no sandbox.
From your own machine
Every cart is a git repository, and the editor is one client of it. Clone it with its address plus .git: a public cart needs nothing, and a private one of yours needs npx ojplay login once per machine first.
git clone https://play.onejs.com/@<handle>/<name>.git
cd <name>
ojplay init # package.json, tsconfig.json and types, all gitignored
npm install
ojplay run # the cart in the site's real container, in a local Chrome
git push origin main # builds on the site, and becomes what everyone playsA push to main builds the commit on the site and, if it builds, makes it what everyone plays. The result comes back on the remote: lines, with the file, line and column of any compile error. The push lands either way, so the last commit that built keeps running until the next one that does.
ojplay is a command you install once, npm install -g ojplay (or prefix each command with npx, which needs no install). It wraps the rest: add, build, typecheck, run, test, status, push, new and runtime, and ojplay help describes each one. Inside a cart that has its own ojplay in node_modules, it runs that one. An AI agent handed a cart should start at agents.md, which the first lines of a new cart's index.tsx point at.
The editor keeps your typing as a draft only you see, and its Push commits on top of whatever main holds by then, so a git push in between is kept: Push lists what came in, and asks which version to keep of any file both changed. Git refuses a push that is not a fast forward, so whoever is second finds out rather than winning. The site does accept a force push, and it replaces what was pushed from the editor, so pull instead.