Engine guide
Unity
WebGL export — up to 80 MB compressed
Unity talks to the outside world via a .jslib plugin +SendMessage callbacks. Wire the Pixlland SDK in 3 files: an edited WebGL template, a JSLib bridge, and a MonoBehaviour that calls into it.
1. Edit the WebGL template
Duplicate Assets/WebGLTemplates/Default to Assets/WebGLTemplates/Pixlland and add the SDK script tag to its index.html:
<!-- inside <head> -->
<script src="https://pixlland.com/sdk/v1/pixlland.js" defer></script>In Player Settings → Resolution and Presentation, pick the Pixlland template.
2. Create the JSLib bridge
Save as Assets/Plugins/WebGL/Pixlland.jslib:
mergeInto(LibraryManager.library, {
PLL_Init: function() {
if (!window.PixllandSDK) return;
window.PixllandSDK.init();
},
PLL_LoadingFinished: function() {
window.PixllandSDK && window.PixllandSDK.gameLoadingFinished();
},
PLL_GameplayStart: function() {
window.PixllandSDK && window.PixllandSDK.gameplayStart();
},
PLL_GameplayStop: function() {
window.PixllandSDK && window.PixllandSDK.gameplayStop();
},
PLL_HappyTime: function(delta) {
window.PixllandSDK && window.PixllandSDK.happyTime(delta);
},
PLL_CommercialBreak: function(cbObjPtr, cbMethodPtr) {
if (!window.PixllandSDK) return;
var cbObj = UTF8ToString(cbObjPtr);
var cbMethod = UTF8ToString(cbMethodPtr);
window.PixllandSDK.commercialBreak().then(function() {
SendMessage(cbObj, cbMethod);
});
},
});3. C# wrapper
using UnityEngine;
using System.Runtime.InteropServices;
public static class Pixlland
{
#if UNITY_WEBGL && !UNITY_EDITOR
[DllImport("__Internal")] public static extern void PLL_Init();
[DllImport("__Internal")] public static extern void PLL_LoadingFinished();
[DllImport("__Internal")] public static extern void PLL_GameplayStart();
[DllImport("__Internal")] public static extern void PLL_GameplayStop();
[DllImport("__Internal")] public static extern void PLL_HappyTime(float delta);
[DllImport("__Internal")] public static extern void PLL_CommercialBreak(string cbObj, string cbMethod);
#else
public static void PLL_Init() {}
public static void PLL_LoadingFinished() {}
public static void PLL_GameplayStart() {}
public static void PLL_GameplayStop() {}
public static void PLL_HappyTime(float d) {}
public static void PLL_CommercialBreak(string a, string b) {}
#endif
}4. Fire from a MonoBehaviour
public class PixllandDriver : MonoBehaviour {
void Start() {
Pixlland.PLL_Init();
Pixlland.PLL_LoadingFinished();
Pixlland.PLL_GameplayStart();
}
void Update() {
if (Time.timeScale > 0)
Pixlland.PLL_HappyTime(Time.unscaledDeltaTime);
}
public void OnPlayerDied() {
Pixlland.PLL_GameplayStop();
Pixlland.PLL_CommercialBreak(gameObject.name, nameof(OnAdFinished));
}
public void OnAdFinished() {
// SendMessage → here
Pixlland.PLL_GameplayStart();
}
}Common pitfalls
- WebGL builds are huge. Strip IL2CPP, enable LTO, and compress with Brotli. Pixlland's ceiling is 80 MB post-compression; beyond that, curation will push back.
- AudioContext suspended. Unity's WebGL audio starts suspended — resume it inside your first user-click handler, not inside
Start().
Alternative: many Unity indies ship a single lightweight scene with vanilla HTML5 + canvas instead. Always worth comparing build sizes.
