Engine reference: bridges, saves, sizes and the fullscreen HUD
The detail behind Engine apps, for when your first build already runs. To ship one, start there.
Godot bridge
Copy chaindaddy.gd and saves.gd into your project and add them as autoloads named ChainDaddy and Saves, in that order. chaindaddy app init godot puts both files in the new project's godot/ folder. Then:
var saved := await Saves.load_save() # from your server: { ok, data }, data your string or null
await Saves.save(JSON.stringify({"level": 3})) # with a fresh session token from the page
var ctx := ChainDaddy.context() # { chainKey, crownId, symbol, signedIn, … }
var bought := await ChainDaddy.buy("skin.gold") # bought.data.statussaves.gd is for progress that follows the player's wallet. For saves on the device, see Saves.
Two things are different in the page's frame:
JavaScriptBridge.evalis refused. The frame's content security policy doesn't allow eval. Reach JavaScript throughJavaScriptBridge.get_interface, aschaindaddy.gddoes.- JSON numbers arrive as floats. Format a crown id with
%dorint():str()gives8.0.
The whole example is Crown Clicker. It keeps the player's taps on the device and on its own server, signs them in and sells the token's store items.
Unity bridge
Put ChainDaddy.jslib in Assets/Plugins/WebGL/ (chaindaddy app init unity writes it, with ChainDaddy.cs, under unity/Assets/: copy that folder into your Unity project). It gives C# two calls: ChainDaddyAction, which sends one action and returns the answer through SendMessage, and ChainDaddyContext.
Call it from C#, on a GameObject whose name you pass, and handle each answer in the method you name:
[DllImport("__Internal")] static extern void ChainDaddyAction(string actionJson, string objectName, string method);
[Serializable] class Answer { public bool ok; public string data; public string error; }
public void SignIn() => ChainDaddyAction("{\"type\":\"sign-in\"}", name, nameof(OnSignedIn));
public void OnSignedIn(string json) { var a = JsonUtility.FromJson<Answer>(json); /* a.ok: signed in */ }ChainDaddy.cs has sign-in, buying, context(), and saves on your own server with a session token (UnityWebRequest), with the editor stubs. For saves on the device, see Saves.
Saves
On the device, with no code. Declare the storage:local permission, and what your game saves is kept in the player's browser and is there when they come back:
- Godot: everything under
user://(FileAccess,ConfigFile,DirAccess).OS.is_userfs_persistent()is true. - Unity:
PlayerPrefs, once you callPlayerPrefs.Save()as on any WebGL build, and files underApplication.persistentDataPath, saved as you write them. On an early Unity 2021.3 patch, from beforeautoSyncPersistentDataPath, those files are saved at the nextPlayerPrefs.Save(). - A web build needs no permission: at its own address,
localStorageand IndexedDB are the browser's own. Each build's preview has its own, so a preview can't read or overwrite a player's save. Don't count on them in Safari: its tracking prevention clears the storage of a game shown inside another site's page when Safari quits. The size limit below, and "only what the engine saves", are for Godot and Unity.
Without the permission a Godot or Unity game still runs, and what it writes lasts until the page closes.
- One app, one browser. Saves are kept for your app, in the browser the player used, on the site they played on: chaindaddy.io and a token's own domain each keep their own. Every token page your app is on there reads the same saves, so put the token in the file name (
context().crownId) if each token should have its own. - A new version keeps them. Saves belong to the app, not to one version of it.
- Up to 16 MB for an app, in at most 4,096 files and folders. A save that would take the app past that isn't kept, none of it, and what was saved before stays. Godot logs
Failed to save IDB file system; Unity logs nothing, so the browser console has a line for it,Saved files not kept. - The player can lose them, and change them. A private window, clearing the site's data, or Safari after seven days without a visit removes them, and a file on the player's device is theirs to edit. Don't keep there what must not be lost or forged.
- Only what the engine saves. There is no other IndexedDB in the frame: a library that wants a database of its own finds none, and Unity's download cache stays off (the browser's own cache keeps your files).
chaindaddy app dev keeps saves the same way, under the same limits.
On every device: your own server. Progress that should follow the player's wallet, and anything players compete on, goes to your server with a session token (see Talk to the page), which proves the signed-in wallet. The Godot example has a small save server that checks the token and keeps each wallet's save.
Size tiers
Sizes are what a player downloads (brotli), for the whole engine/ folder and any paid/ folder together:
| Tier | Download | Who gets it |
|---|---|---|
| S | up to 16 MB | Every reviewed engine app |
| M | up to 64 MB | On request |
Whatever the tier, the export may be at most 256 MB uncompressed, and 64 MB for any one file. A phone has to hold the game in memory.
Godot's engine alone is about 8 MB to download, so a small Godot game fits in S. A small Unity release build is about 6 MB.
Keep the corners clear in fullscreen
When your game fills the screen, the page draws a small HUD over its corners, outside your frame: the page token's price, Trade and Exit fullscreen. It fades away while the player plays and comes back when they move the mouse or tap its handle. Your game keeps the keyboard and gamepad throughout, and nothing you draw can cover it. All you do is leave it room:
| Corner | While playing | When the HUD is open |
|---|---|---|
| Bottom right | The handle: keep the last 48×48 px free of anything a player must press | The bar, about 360×72 px (200×72 px on a phone) |
| Top right | Nothing | The price, about 240×96 px |
| Top left | A faint Chain Daddy mark, about 64×64 px, unless the page's plan took it off | The same mark |
Read isFullscreen to know when this applies. In fullscreen the frame's speaker button is gone, so keep your own sound controls. To see the HUD at these sizes, run chaindaddy app dev and open its fullscreen view: the HUD mark, HUD price and HUD Trade switches play what a page's plan and owner can turn off.