Skip to content

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:

gdscript
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.status

saves.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.eval is refused. The frame's content security policy doesn't allow eval. Reach JavaScript through JavaScriptBridge.get_interface, as chaindaddy.gd does.
  • JSON numbers arrive as floats. Format a crown id with %d or int(): str() gives 8.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:

csharp
[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 call PlayerPrefs.Save() as on any WebGL build, and files under Application.persistentDataPath, saved as you write them. On an early Unity 2021.3 patch, from before autoSyncPersistentDataPath, those files are saved at the next PlayerPrefs.Save().
  • A web build needs no permission: at its own address, localStorage and 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:

TierDownloadWho gets it
Sup to 16 MBEvery reviewed engine app
Mup to 64 MBOn 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:

CornerWhile playingWhen the HUD is open
Bottom rightThe handle: keep the last 48×48 px free of anything a player must pressThe bar, about 360×72 px (200×72 px on a phone)
Top rightNothingThe price, about 240×96 px
Top leftA faint Chain Daddy mark, about 64×64 px, unless the page's plan took it offThe 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.