Back

Developer docs

Everything you need to publish an HTML5 game on UNTILS. Pick a section below.

Get started

Build your game, pack the zip and pick the right size.

Quick start

  1. Make your game as a normal HTML5 game with an index.html.
  2. (Recommended) Download the SDK below and add it to your game.
  3. Put everything in one .zip file. index.html must be at the top level of the zip.
  4. Open your dashboard, press + ADD NEW GAME, fill in the details, add your icon and zip, and press UPLOAD GAME.
  5. Our team reviews it (up to 2 days). After approval we make it live on UNTILS.

The starter game already uses every SDK command. Upload it as a test game to see how publishing works.

Game package (the zip)

ItemRule
FormatOne .zip file. index.html at the top (not inside a sub-folder).
Max size50 MB. We recommend under 20 MB so the game loads fast on mobile data.
File pathsUse relative paths: game.js, img/hero.png. Do not start paths with /, because your game runs inside /live/....
TechnologyHTML5, JavaScript, Canvas, WebGL, WebAssembly. Web exports from Unity, Cocos and Godot work as long as the export has an index.html. Unity, Cocos and Godot each have their own SDK.
Starts by itselfNo login, no installs, no pop-ups. The game must start from the Play screen.
Good to know: your game runs in a protected sandbox. It cannot read UNTILS accounts or cookies. Browser localStorage is saved for you automatically, and the SDK gives you a cleaner way to save (see below).

Device: mobile or desktop

When you upload, choose Mobile game if it plays well on phones and PC. Choose Desktop game if it needs a keyboard or mouse. Desktop games show "This game is for desktop (PC) only" on phones instead of a Play button.

Recommended game size (what the player sees)

WhereWhat to do
PCDesign for 1280 x 720 (16:9 landscape). The game area is shown in a 16:9 frame and can go fullscreen.
PhoneWhen the player presses Play, the game opens fullscreen. Support portrait (720 x 1280) or landscape, and tell players if one is required.

Most important: make the game responsive. It must fill the window (window.innerWidth x window.innerHeight), keep its aspect ratio, and never need scrolling. Add this to your page:

<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<style>html,body{margin:0;height:100%;overflow:hidden;touch-action:manipulation}</style>

Unity, Cocos, Godot and other engines

Web (HTML5) exports from game engines work if the zip follows the same rules as above: index.html at the top, relative paths, under 50 MB.

Unity (WebGL)

  1. File → Build Settings → WebGL → Build.
  2. In Player Settings → Publishing Settings: Compression Format can be Brotli, Gzip or Disabled (UNTILS serves all three). We recommend Gzip with Decompression Fallback ON. Turn Data Caching OFF.
  3. Zip the contents of the build folder (index.html, Build/, TemplateData/) so index.html is at the top of the zip.
  4. Make the canvas fill the window so it works on phones and PC.
Using Unity? Use the Unity SDK. It adds the WebGL template and UntilsPrefs so progress is saved.

Cocos Creator (Web)

  1. Project → Build → Platform Web Mobile → Build.
  2. Zip the contents of the build folder, so index.html is at the top of the zip.
Using Cocos Creator? Use the Cocos SDK. It adds UntilsPrefs so progress is saved, and sends loading and pause events for you.

Godot

Using Godot? Use the Godot SDK. It is a plugin that adds saves, loading and pause events for you. Export for Web (Godot 3: HTML5), turn Thread Support off, and zip the export as above.
Digital Kit

Icon, banner, thumbnail, screenshots, text logo and video for your game page.

Game icon (logo) - required

ItemRule
ShapeSquare (width = height).
SizeMinimum 512 x 512 px. We recommend 1024 x 1024 px. Smaller or non-square icons are rejected by the upload form.
FormatPNG, JPG or WebP. Under 2 MB.

What to put in it:

  • One clear subject: your main character, object or logo mark, in the centre.
  • Keep about 10% empty space around the edges. UNTILS rounds the corners itself, so do not round them.
  • Bright, high-contrast colours and a solid background. It must look good very small (about 60 px).
  • Little or no text. Tiny text becomes unreadable. A short game name in large letters is fine.
  • No borders, no store badges, no "NEW" or "FREE" stickers, no blurry or stretched images.
  • Only artwork you made or are allowed to use. No copied characters or logos.

The icon is shown on the game card, the Play screen, "More games" and the popular banner.

Thumbnail - optional

The thumbnail is a wide picture that shows your game at a glance. UNTILS can use it on game cards and in lists, so players see the real look of your game together with its name.

ItemRule
ShapeLandscape (wider than tall). We recommend 1280 x 720 px (16 : 9). Minimum 960 px wide.
FormatPNG, JPG or WebP. Under 2 MB.
Name logoPut your game name as a text logo slightly above the centre of the picture, in large, easy-to-read letters.
CentreBelow the logo, in the middle, show only the core of your game: the main character, object or scene.
No UINo other UI and no other text. No buttons, scores, menus, joysticks, slogans, store badges or "NEW" / "FREE" stickers.

Tip: keep the important art away from the edges, because the picture is cropped a little on small cards.

Screenshots - optional

ItemRule
CountUp to 5.
SizeMinimum 640 px wide. We recommend 1280 x 720 (landscape) or 720 x 1280 (portrait for phone games).
FormatPNG, JPG or WebP. Under 2 MB each.

What to show: real screenshots taken from your running game, exactly as the player sees it, with all the UI, text and buttons (menu, gameplay, a level, a win or upgrade screen). They must not be edited, redrawn or mocked up. No device frames, no added promo text, no screens from other games.

Screenshots appear at the very bottom of your game page. Click one to see it large. You can remove or add screenshots later from the dashboard.

Gameplay video - optional

A short video that shows how your game plays. UNTILS can show it on your game page before the screenshots.

ItemRule
LengthMaximum 15 seconds. Longer videos are rejected.
FormatMP4 (H.264) or WebM. Under 20 MB.
Size1280 x 720 (landscape) or 720 x 1280 (portrait for phone games).
SoundThe video starts muted, so sound is optional. If you add sound, keep it quiet and without copyrighted music.
No UIThe video must have no UI at all: no text, no buttons, no controls, no score, no joystick, no menus, no tutorials. Show only the core of the game: the main characters and the action.
ContentReal gameplay only: start with the action in the first second, show the main mechanic, end cleanly. No fake or edited-in scenes, no ads or promo banners, no watermarks, no black bars, no scenes from other games.

Best Game Art for your game

See art styles that work well, and pick the one that fits your game.

2D Art

Choose one 2D style and use it everywhere: characters, backgrounds, buttons and icons. A game that looks the same from screen to screen feels finished. Tap any example to see it bigger.

  • Use PNG or WebP for art. Keep images only as big as they are shown, so your zip stays small (the limit is 50 MB).
  • Keep buttons and important things big enough for a thumb on a phone.
  • Make sure text and the player stay easy to see against the background.

3D Art Style

For 3D games, pick one style and keep every model, texture and light in the same style. Tap any example to see it bigger.

  • Keep models light (fewer triangles) so the game runs smoothly on phones.
  • Use small, compressed textures, and share one texture between many objects when you can.
  • Go easy on real-time shadows and effects. Test on a mid-range phone, not only on a PC.
SDK

Connect your game to UNTILS: HTML5, Unity, Cocos and Godot, and every SDK command.

HTML SDK

HTML SDK (version 1.2.0) is one small file, untils.js, for HTML5 games. It gives your game progress saving, pause/resume, share links, language, fullscreen and event tracking. Ads and leaderboards are reserved and will work later without changing your code. It is optional, but recommended.

Import

  1. Download untils.js.
  2. Put it next to your index.html inside your game folder (and so inside the zip).
  3. Add this in your page before your own game script:
<script src="untils.js"></script>

Using a local copy means your game also runs on your own PC without UNTILS. In that case the SDK switches to offline mode: saves go to your browser and ads are skipped, so nothing crashes.

Full flow

async function main() {
  await Untils.init();               // 1. always first

  Untils.loadingStart();             // 2. assets start loading
  await loadAssets();
  Untils.loadingFinished();          // 3. menu is ready

  let level = await Untils.load("level", 1);   // 4. read saved progress

  playBtn.onclick = () => {
    Untils.gameplayStart();          // 5. player starts playing
  };

  function onGameOver() {
    Untils.gameplayStop();           // 6. player died / opened menu
    Untils.save("level", level);     // 7. save progress
    Untils.showAd("interstitial");   // 8. ad between levels (not live yet)
  }

  rewardBtn.onclick = async () => {
    const watched = await Untils.showAd("rewarded");   // 9. watch ad for a reward
    if (watched) giveCoins();
  };

  Untils.onPause(() => pauseGame());     // tab hidden / app switched
  Untils.onResume(() => resumeGame());
}
main();

SDK commands

CommandWhat it doesStatus
await Untils.init({ debug })Starts the SDK. Call it first. Resolves with { name, version, env, isMobile, player, language }. env is "untils" on the site or "offline" on your own PC. Never fails. Waits up to 3 seconds for UNTILS.Live
loadingStart() / loadingFinished()Tell UNTILS when your game is loading and when the menu is ready.Live
gameplayStart() / gameplayStop()Call when real play starts and stops (death, menu, pause). Repeated calls are ignored. When the tab is hidden, the SDK stops gameplay for you, so call gameplayStart() again when the player returns.Live
Untils.save(key, value)Saves any JSON value (number, text, object, array). Returns true or false.Live (this browser)
await Untils.load(key, fallback)Reads it back. Returns fallback if nothing is saved.Live (this browser)
remove(key), clearSave(), keys()Delete one value, delete everything, or list saved keys.Live
onPause(fn) / onResume(fn)Runs when the player leaves or returns to the tab. Pause your game and sound here.Live
await getPlayer()Returns { guest, name }. Everyone is "Guest" for now.Basic
Untils.getLanguage()Player's language as a 2-letter code, like "en" or "hi".Live
Untils.shareableURL({ level: 5 })Returns a link to your game with your own values in it. Show it in a "Share" button.Live
Untils.getURLParam("level")Reads a value from the link the player opened. Returns undefined if missing.Live
requestFullscreen() / exitFullscreen()Asks UNTILS to enter or leave fullscreen. Call it from a button click.Live
Untils.track(name, data)Sends your own event, like track("level_complete", { level: 3 }). Name up to 40 characters. Stats for developers are coming later.Reserved
Untils.setDebug(true)Prints SDK activity to the browser console while you build.Live
Untils.isMobile, env, isReady, versionHandy flags.Live
await showAd("interstitial" | "rewarded"), commercialBreak(), rewardedBreak()Ads are not live yet. Until then interstitial returns true at once and rewarded returns false, so you can write your ad code now. commercialBreak() and rewardedBreak() are shortcuts.Coming soon
await submitScore(board, score)Sends a score. Returns false until leaderboards go live. Safe to call now.Coming soon
Limits and tips: all saved values together can be about 900 KB per game. If you go over, save() returns false and prints a warning. Save small things (level, coins, settings), not big data. Today saves stay in the player's browser on that device. When player accounts arrive, the same save and load will work on every device, so your game needs no change.

Unity SDK (beta, Unity 2020.1 to Unity 6, WebGL)

Pick the package for your Unity version from the list below, newest first (Unity 2019 and older are not supported, they use an older WebGL loader). Every package has everything you need: the C# SDK, the Untils WebGL template (it appears in Player Settings, like other platform SDK templates), UntilsPrefs (a save-safe replacement for PlayerPrefs), an editor menu and a sample script.

Your Unity versionSDK versionDownload
Unity 6 (6000.x) (latest)
Unity 2023.x can use this one too
Unity SDK 1.1.0
Unity 2022.3 LTSUnity SDK 1.1.0
Unity 2021.3 LTSUnity SDK 1.1.0
Unity 2020.3 LTSUnity SDK 1.1.0

Install and build

  1. Unzip the file into your Unity project folder (the one that contains Assets). Merge the Assets folder.
  2. In Unity open the menu Untils → Apply recommended WebGL settings. This sets everything in the table below for you.
  3. In your first script call Untils.Init(...) and use UntilsPrefs instead of PlayerPrefs (see the code below).
  4. File → Build Settings → WebGL → Build.
  5. Zip the contents of the build folder, so index.html is at the top of the zip, and upload it in your dashboard. UNTILS then opens the Inspector view to check your SDK.
Player Settings (WebGL)Value
Resolution and Presentation → WebGL TemplateUntils
Publishing Settings → Compression FormatGzip (Brotli or Disabled also work)
Publishing Settings → Decompression FallbackOn
Publishing Settings → Data CachingOff

The template makes your game fill the whole window (phones and PC), shows a loading bar, loads untils.js, starts the SDK, and tells UNTILS when loading starts and finishes. You do not need to call LoadingStart yourself.

Code

using UnityEngine;

public class GameManager : MonoBehaviour
{
    int level;

    void Start()
    {
        Untils.Init(ok =>
        {
            level = UntilsPrefs.GetInt("level", 1);    // saved progress
            StartGame();
        });
        Untils.OnPause  += () => Debug.Log("paused");   // optional
        Untils.OnResume += () => Debug.Log("resumed");
    }

    public void OnPlayPressed() { Untils.GameplayStart(); }

    public void OnGameOver()
    {
        Untils.GameplayStop();
        UntilsPrefs.SetInt("level", level);             // saved automatically
        Untils.CommercialBreak(() => ShowGameOverScreen());   // ads not live yet: continues at once
    }

    public void OnRewardButton()
    {
        Untils.RewardedBreak(rewarded => { if (rewarded) GiveCoins(); });
    }
}

Commands

CommandWhat it doesStatus
Untils.Init(Action<bool> onReady)Starts the SDK and loads saved data. Call it first. onReady runs when ready.Live
UntilsPrefs.SetInt / GetInt / SetFloat / GetFloat / SetString / GetString / HasKey / DeleteKey / DeleteAll / SaveSame as PlayerPrefs. Saves itself shortly after each change. About 900 KB per game.Live (this browser)
Untils.GameplayStart() / GameplayStop()Real play starts / stops (death, menu, pause).Live
Untils.LoadingStart() / LoadingFinished()Done for you by the template. Only call them if you load more content later.Live
Untils.OnPause / OnResumeEvents when the tab is hidden or shown. With Untils.AutoPause = true (default) the SDK also pauses Time.timeScale and audio for you.Live
Untils.IsMobile, Language, Env, IsReady, PlayerHandy values. Env is "untils" on the site and "editor" in the Unity Editor.Live
Untils.GetPlayer(callback)Returns the player (guest, name). Everyone is "Guest" for now.Basic
Untils.ShareableURL(dictionary) / GetURLParam(name)Make a share link with your values, and read them back when the game is opened from that link.Live
Untils.RequestFullscreen() / ExitFullscreen()Ask UNTILS to enter or leave fullscreen. Call from a button press.Live
Untils.Track(name, json)Send your own event, like Track("level_complete", "{\"level\":3}"). Stats come later.Reserved
Untils.CommercialBreak(callback), RewardedBreak(callback), ShowAd(type, callback)Ads are not live yet. The interstitial continues at once; the rewarded callback gets false.Coming soon
Untils.SubmitScore(board, score, callback)Leaderboards. Returns false until they go live.Coming soon
Untils.SetDebug(true)Prints SDK activity in the browser console.Live
In the Unity Editor nothing is sent anywhere: UntilsPrefs uses PlayerPrefs, and rewarded ads return Untils.EditorRewardedResult (default true) so you can test your reward code.

If something goes wrong

  • "untils.js is not loaded" in the browser console: the WebGL template is not set to Untils. Run the menu Untils → Apply recommended WebGL settings and build again.
  • Progress is not saved: you used PlayerPrefs. Change it to UntilsPrefs. Unity's own save uses IndexedDB, which is blocked in the UNTILS sandbox.
  • The game stays on the loading bar: open the browser console (F12). Check that the zip has index.html at the top and the Build folder next to it.
  • Very large builds: keep the zip under 50 MB. Compress textures and audio.

This SDK is in beta. If you find a problem, please tell us through the contact page and include your Unity version.

Cocos SDK (beta, Cocos Creator 2.4 and 3.x, Web)

Pick the package for your Cocos Creator version. Both have the same commands. Each one has everything you need: the SDK script, UntilsPrefs (a save-safe replacement for the local storage), a sample script, and untils.js already placed in build-templates, so it is copied into your build for you.

Your Cocos Creator versionSDK versionDownload
Cocos Creator 3.x (3.0 and newer)
TypeScript
Cocos SDK 1.0.0
Cocos Creator 2.4.x
JavaScript
Cocos SDK 1.0.0

Install and build

  1. Unzip the file into your Cocos project folder (the one that contains assets). Merge the folders. You get assets/UntilsSDK and build-templates/web-mobile/untils.js.
  2. In your first script call Untils.init() and use UntilsPrefs instead of the local storage (see the code below).
  3. Project → Build → Platform: Web Mobile → Build. Web Mobile works on phones and PC. Set the build Orientation to match the Mobile screen option you choose in the dashboard.
  4. Open the build folder and check that untils.js is next to index.html.
  5. Zip the contents of the build folder, so index.html is at the top of the zip, and upload it in your dashboard. UNTILS then opens the Inspector view to check your SDK.

You do not need to call loadingStart / loadingFinished: the SDK sends them for you (set Untils.autoLoading = false to do it yourself). When the tab is hidden the SDK also pauses the game and sound, and resumes them when the player returns (set Untils.autoPause = false to handle it yourself).

Code

Cocos Creator 3.x (TypeScript)

import { _decorator, Component } from 'cc';
import { Untils, UntilsPrefs } from './UntilsSDK/Untils';
const { ccclass } = _decorator;

@ccclass('GameManager')
export class GameManager extends Component {
    level = 1;

    start() {
        Untils.onPause(() => console.log('paused'));      // optional
        Untils.onResume(() => console.log('resumed'));

        Untils.init().then(() => {
            this.level = UntilsPrefs.getInt('level', 1);    // saved progress
            this.startGame();
        });
    }

    onPlayPressed() { Untils.gameplayStart(); }

    onGameOver() {
        Untils.gameplayStop();
        UntilsPrefs.setInt('level', this.level);            // saved automatically
        Untils.commercialBreak().then(() => this.showGameOverScreen());   // ads not live yet: continues at once
    }

    onRewardButton() {
        Untils.rewardedBreak().then((rewarded) => { if (rewarded) this.giveCoins(); });
    }
}

Cocos Creator 2.4.x (JavaScript)

const { Untils, UntilsPrefs } = require("Untils");

cc.Class({
    extends: cc.Component,

    start: function () {
        var self = this;
        Untils.onPause(function () { cc.log("paused"); });     // optional
        Untils.onResume(function () { cc.log("resumed"); });

        Untils.init().then(function () {
            self.level = UntilsPrefs.getInt("level", 1);       // saved progress
            self.startGame();
        });
    },

    onPlayPressed: function () { Untils.gameplayStart(); },

    onGameOver: function () {
        Untils.gameplayStop();
        UntilsPrefs.setInt("level", this.level);               // saved automatically
        Untils.commercialBreak().then(function () { /* show game over screen */ });
    },

    onRewardButton: function () {
        Untils.rewardedBreak().then(function (rewarded) { if (rewarded) { /* give coins */ } });
    }
});

Commands

CommandWhat it doesStatus
Untils.init({ debug })Starts the SDK and loads saved data. Call it first. Returns a promise that resolves with { name, version, env, isMobile, player, language }. Never fails. Waits up to 3 seconds for UNTILS.Live
UntilsPrefs.setInt / getInt / setFloat / getFloat / setString / getString / setBool / getBool / setJSON / getJSON / hasKey / keys / deleteKey / deleteAll / saveSave and read your data, like the local storage. Saves itself shortly after each change. About 900 KB per game. setJSON keeps any object or array.Live (this browser)
Untils.save(key, value), load(key, fallback), remove(key), clearSave(), keys()The same saves in the style of the HTML SDK (promises).Live (this browser)
Untils.gameplayStart() / gameplayStop()Real play starts / stops (death, menu, pause). Repeated calls are ignored.Live
Untils.loadingStart() / loadingFinished()Done for you. Only call them yourself if you set autoLoading = false, or if you load more content later.Live
Untils.onPause(fn) / onResume(fn) / offPause(fn) / offResume(fn)Runs when the tab is hidden or shown. With Untils.autoPause = true (default) the SDK also pauses the game loop and sound for you.Live
Untils.isMobile, language, env, isReady, player, versionHandy values. env is "untils" on the site and "offline" in the Cocos preview or on your own PC.Live
Untils.getPlayer()Promise with { guest, name }. Everyone is "Guest" for now.Basic
Untils.shareableURL({ level: 5 }) / getURLParam("level")Make a share link with your values, and read them back when the game is opened from that link.Live
Untils.requestFullscreen() / exitFullscreen()Ask UNTILS to enter or leave fullscreen. Call from a button press.Live
Untils.track(name, data)Send your own event, like track("level_complete", { level: 3 }). Name up to 40 characters. Stats come later.Reserved
Untils.commercialBreak(), rewardedBreak(), showAd(type)Ads are not live yet. The interstitial continues at once; the rewarded promise gives false.Coming soon
Untils.submitScore(board, score)Leaderboards. Returns false until they go live.Coming soon
Untils.setDebug(true)Prints SDK activity in the browser console.Live
In the Cocos preview (and on your own PC) nothing is sent to UNTILS: saves stay in your browser, and a rewarded ad returns Untils.editorRewardedResult (default true) so you can test your reward code.

If something goes wrong

  • "untils.js was not found" in the browser console: the file is not next to index.html in your build. Check that build-templates/web-mobile/untils.js exists in your project and build again.
  • Progress is not saved: you used the engine's own local storage. Change it to UntilsPrefs. Browser storage is blocked in the UNTILS sandbox.
  • The game stays on the loading screen: open the browser console (F12). Check that the zip has index.html at the top, with the assets and src (or cocos-js) folders next to it.
  • Sound does not start: browsers only allow sound after the first tap or click. Start your music from a button press.
  • Very large builds: keep the zip under 50 MB. Compress textures and audio.

This SDK is in beta. If you find a problem, please tell us through the contact page and include your Cocos Creator version.

Godot SDK (beta, Godot 3.x and 4.x, Web)

Pick the package for your Godot version. Both have the same commands. Each one is a Godot plugin: it adds the Untils Autoload for you, with saves (like PlayerPrefs), loading and gameplay events, pause handling, and a sample script. The web SDK is already inside it, so there is nothing else to copy.

Your Godot versionSDK versionDownload
Godot 4.x
GDScript 2, "Web" export
Godot SDK 1.0.0
Godot 3.x (3.5 recommended)
GDScript, "HTML5" export
Godot SDK 1.0.0

Install and export

  1. Unzip the file into your Godot project folder (the one that contains project.godot). Merge the folders. You get addons/untils_sdk.
  2. Project → Project Settings → Plugins: tick Enable for UNTILS SDK. This adds the Autoload Untils. (You can also add addons/untils_sdk/Untils.gd yourself as an Autoload named Untils.)
  3. In your first script call Untils.init() and use Untils.set_int / get_int ... instead of user:// files (see the code below).
  4. Project → Export → Add... → Web (Godot 3: HTML5). Turn Thread Support off (Godot 3: Export Type Regular), because threads need special server headers. In Project Settings → Display → Window → Stretch use Mode canvas_items (Godot 3: 2d) and Aspect expand so the game fits phones and PC.
  5. Click Export Project, name the file index.html, and export into an empty folder. Zip the contents of that folder, so index.html is at the top of the zip, and upload it in your dashboard. UNTILS then opens the Inspector view to check your SDK.

You do not need to call loading_start / loading_finished: the SDK sends them for you (set Untils.auto_loading = false to do it yourself). When the tab is hidden the SDK also pauses the game and sound, and resumes them when the player returns (set Untils.auto_pause = false to handle it yourself).

Code

Godot 4.x

extends Node

var level = 1

func _ready():
    Untils.paused.connect(func(): print("paused"))       # optional
    Untils.resumed.connect(func(): print("resumed"))

    var info = await Untils.init()
    level = Untils.get_int("level", 1)                   # saved progress
    start_game()

func on_play_pressed():
    Untils.gameplay_start()

func on_game_over():
    Untils.gameplay_stop()
    Untils.set_int("level", level)                       # saved automatically
    await Untils.commercial_break()                      # ads not live yet: continues at once
    show_game_over_screen()

func on_reward_button():
    var rewarded = await Untils.rewarded_break()
    if rewarded:
        give_coins()

Godot 3.x

extends Node

var level = 1

func _ready():
    Untils.connect("paused", self, "_on_paused")         # optional
    Untils.connect("resumed", self, "_on_resumed")

    var info = yield(Untils.init(), "completed")
    level = Untils.get_int("level", 1)                   # saved progress
    start_game()

func on_play_pressed():
    Untils.gameplay_start()

func on_game_over():
    Untils.gameplay_stop()
    Untils.set_int("level", level)                       # saved automatically
    yield(Untils.commercial_break(), "completed")        # ads not live yet: continues at once
    show_game_over_screen()

func on_reward_button():
    var rewarded = yield(Untils.rewarded_break(), "completed")
    if rewarded:
        give_coins()

Commands

CommandWhat it doesStatus
Untils.init(debug)Starts the SDK and loads saved data. Call it first. Returns a Dictionary { name, version, env, isMobile, player, language } (also sent with the initialized signal). Never fails. Waits up to 3 seconds for UNTILS.Live
Untils.set_int / get_int / set_float / get_float / set_string / get_string / set_bool / get_bool / set_json / get_json / has_key / keys / delete_key / delete_all / save_nowSave and read your data, like PlayerPrefs. Saves itself shortly after each change. About 900 KB per game. set_json keeps any Dictionary or Array (JSON types only).Live (this browser)
Untils.gameplay_start() / gameplay_stop()Real play starts / stops (death, menu, pause). Repeated calls are ignored.Live
Untils.loading_start() / loading_finished()Done for you. Only call them yourself if you set auto_loading = false, or if you load more content later.Live
Signals paused / resumedRun when the tab is hidden or shown. With Untils.auto_pause = true (default) the SDK also pauses the game (get_tree().paused) and mutes the Master audio bus for you.Live
Untils.is_mobile, language, env, is_ready, playerHandy values. env is "untils" on the site, "offline" in a web build on your own PC, and "editor" when you run from the Godot editor.Live
Untils.get_player()Dictionary with guest and name. Everyone is "Guest" for now.Basic
Untils.shareable_url({ "level": 5 }) / get_url_param("level")Make a share link with your values, and read them back when the game is opened from that link.Live
Untils.request_fullscreen() / exit_fullscreen()Ask UNTILS to enter or leave fullscreen. Call from a button press.Live
Untils.track(name, data)Send your own event, like track("level_complete", {"level": 3}). Name up to 40 characters. Stats come later.Reserved
Untils.commercial_break(), rewarded_break(), show_ad(type)Ads are not live yet. The interstitial continues at once; rewarded_break() gives false. Also sends the ad_finished signal. In the editor and offline, a rewarded ad gives Untils.editor_rewarded_result (default true) so you can test your reward code.Coming soon
Untils.submit_score(board, score)Leaderboards. Returns false until they go live.Coming soon
Untils.set_debug(true)Prints SDK activity in the Output panel and the browser console.Live

If something goes wrong

  • "Call Untils.init() first" warning: you used a save or event command before init() finished. Wait for await Untils.init() (Godot 3: yield(Untils.init(), "completed")) in your first script.
  • Untils is not found: the plugin is not enabled. Tick Enable in Project Settings → Plugins, or add Untils.gd as an Autoload named Untils.
  • Progress is not saved: you used user:// files or ConfigFile. Browser storage is blocked in the UNTILS sandbox. Use Untils.set_int and the other save commands.
  • The game does not start, or shows a "SharedArrayBuffer" error: Thread Support is on. Turn it off in the export settings and export again (Godot 3: Export Type Regular).
  • Sound does not start: browsers only allow sound after the first tap or click. Start your music from a button press.
  • Large exports: keep the zip under 50 MB. Compress textures and audio, and remove unused export templates.

This SDK is in beta. If you find a problem, please tell us through the contact page and include your Godot version.

Test and publish

Check your game in the Inspector, pass review and go live.

Inspector view and SDK check

Before a game or a new version (new zip) is uploaded, UNTILS checks your zip for the Untils SDK. If the SDK is missing, a red panel appears and the upload does not start, so integrate the SDK first and upload again. After the upload, UNTILS opens an Inspector view panel in your dashboard. It starts your game in the background and checks whether the Untils SDK is running, and the panel confirms the result.

The panel always has a link to the Inspector page. There your game opens like on UNTILS, with a console on the side that shows each event as it happens:

  • init: the SDK started (and which SDK and version).
  • loading start and finished, gameplay start and stop.
  • save: how many keys and how big, and track events with their data.
  • ad and score requests (ads and leaderboards are not live yet).
  • error: errors from your game, when the SDK is running.

Chips at the top turn green when an event has fired. You can switch between Desktop and Phone size, restart the game, and copy the log.

When does the panel appear? Only when you upload a zip (first upload or a new version). It does not appear when you only change the text, category, icon, banner or screenshots. You can open the Inspector at any time from your game's details in the dashboard. For a live game with a new version waiting for review, you can inspect the new version too.

Review and going live

  1. PENDING - your game is waiting. Our team plays it on PC and phone and writes reviews. Review takes up to 2 days. While you wait, click your game in the dashboard and press Preview on UNTILS to play it on a UNTILS game page. The preview link works for 24 hours.
  2. APPROVED or REJECTED - the leader decides. If rejected, a note explains why on your dashboard, and you can fix it and upload again.
  3. LIVE - the game is public on UNTILS. A green PLAY button appears next to it in your dashboard, together with plays, players and likes. Messages from our team also show there, next to the game.
Updating a live game: click it in your dashboard to change the name, description, category, icon, banner, screenshots, or upload a new version. If you rename a game, its link changes too. Changes to the name, description, category, icon, banner and screenshots go live right away when you press SAVE CHANGES. A new version (new zip) of a live game is reviewed first: it shows as "New version in review" and the current version keeps running until we approve it (up to 2 days).

Rules

  • Your game must be yours, or you must have the right to publish it.
  • No adult content, hate, or violence aimed at real people.
  • No malware, crypto-mining, tracking, or collecting players' personal data.
  • No misleading names, icons, screenshots or banners.
  • The game must work, load in a reasonable time, and not crash.

Questions? Use the contact page.