Setting up a JavaScript Playable for Unity Playworks
Unity Playworks offers support for JavaScript playables, created outside of the Unity Playworks Plugin. You can benefit from all of the features such as playable variations, multi-ad network support and playable ad analytics.
This guide outlines the steps necessary to adapt your JavaScript playable ad for us with Unity Playworks.
Before continuing with the steps on this page please be sure to have downloaded your HTML5 playable from your provider, or as an export from the game engine being used.
Step by step
1. Make sure your html file is named "source.html"
2. Make sure all the startup functionality is performed in the startGame()
function
3. Create 2 json files
The name of these files needs to be luna.json
and the other playground.json
, these will be necessary for uploading to Unity Playworks.
4. Populate your playground.json
Within your playground.json
you will need to create a new object with 2 fields; "title" & "icon", and another object within it called "fields".
Example of how this should look below:
{
"title": "Basic Playable",
"icon": "", // Icon next to the playable in Unity Playworks, takes a Data URL.
"fields": {} // You can populate this with any settings you wish to be editable in Unity Playworks
}
If you would like an example of how to populate the fields object for Unity Playworks click here.
5. Within your luna.json
add the following:
{
"unity": {
"packages": {
"default": {
"applicationName": "",
"iosLink": "",
"androidLink": "",
"orientation": "unspecified",
"supportedLanguages": ["en"]
},
"ironsource": {
"appID": "",
"assetID": "",
"applicationGenre": "",
"versionName": "",
"apiType": 0,
"playableMode": 0,
"packageType": 0
},
"facebook": {
"assetID": "",
"packageType": 0
},
"tiktok": {
"orientation": 0
}
}
}
}
To learn about what should be entered in each field in your luna.json
click here.
6. Add callback events to your playable
To diplay the events when they are triggered, we can create a log
function that will show the messages directly in the window.
Let's add some style to the logs by adding the following code in a <style>
tag in the <head>
of our project.
#log {
position: absolute;
background: black;
display: block;
color: white;
bottom: 0;
height: 30%;
width: 90%;
font-size: 2%;
padding: 5%;
}
Create a container for the debug messages in the <body>
of our playable:
<!-- container element for debug messages -->
<label id="log"></label>
Add a <script>
tag with the following function:
function log(text) {
document.getElementById('log').innerHTML += text + '<br />';
}
Finally, we can subscribe to the event and have a debug message on our window every time the events is triggered. For example:
// Subscribe to luna:build event – will be fired right after 'load' event of the window.
window.addEventListener('luna:build', function () {
log('Playable is about to start');
});
You can see a list of our callback events by clicking here.
You can find an example of this in our repository.
7. Use the Unity Playworks API to direct the user to the app store
The API call needed: Luna.Unity.Playable.InstallFullGame()
8. Extra step if you wish to run on Mintegral or Vungle
If you wish to run on Mintegral or Vungle, please also call the Luna.Unity.LifeCycle.GameEnded()
event when the game is complete.
9. Zip your playable & json files
The last step is to zip your 3 files (source.html
, luna.json
, playground.json
). Then drag and drop the resulting zip at the bottom of the playground.lunalabs.io/apps page. (You can also click on the browse text at the bottom of the page, navigate to where the zip is in the opened window and hit open).
Optional Extra Steps
- Update your
luna.json
file with your app store URLs. (Click here to learn about what to put in each field) - Update your
playground.json
file with parameters in your game, for quick editing in Unity Playworks. - Use Unity Playworks Custom Events. (see below)
Custom Events
It is possible to use the Unity Playworks Analytics events API for custom events in your playable. Please see here for full documentation of the API, and here for information on Events Settings.
Implementation Example:
window.pi.logCustomEvent('LevelFailed', 1);
window.pi.logCustomEvent('EndCardShown');
luna.json guide
Click the arrow below to see a table comprising all you need to know regarding each field in the luna.json
file.
CLICK ME
Section | Field Name | Data Type | Description |
---|---|---|---|
default | applicationName | String | Your playable's name |
default | iosLink | String | Your iOS App Store link |
default | androidLink | String | Your Android App Store link |
default | orientation | String | Can be one of: "unspecified", "portrait" or "landscape" |
default | supportedLanguages | Array of Strings | List the languages your playable supports via listing the corresponding language codes (formatted like this: "en", "fr", ...) |
ironsource | appID | String | Optional |
ironsource | assetID | String | Optional |
ironsource | applicationGenre | String | Optional |
ironsource | versionName | String | Optional |
ironsource | apiType | int | Enter either 0 or 1: 0 for DAPI, 1 for NUCLEO |
ironsource | playableMode | int | Enter either 0 or 1: 0 for PA, 1 for IEC |
ironsource | packageType | int | Enter either 0 or 1: 0 for Inline, 1 for CDN |
assetID | String | Optional | |
packageType | int | Enter either 0 or 1: 0 if your are submitting using a ZIP file (5Mb limit), or 1 for a single inlined HTML file (2Mb limit) | |
tiktok | orientation | int | Enter 0, 1 or 2: 0 for "responsive", 1 for "portrait" or 2 for "landscape" |
Fields example
Click the arrow below to view an example of how to populate the fields object for Unity Playworks.
CLICK ME
"fields": {
"ShapeController": {
"shapeColor": {
"title": "shapeColor",
"type": "color",
"defaultValue": [
1,
0,
0,
1
],
"section": "",
"order": 1,
"localization": 0,
"options": {}
},
"shape": {
"title": "shape",
"type": "enum",
"defaultValue": 1,
"section": "",
"order": 2,
"localization": 0,
"options": {
"0": "CUBE",
"1": "SPHERE",
"2": "CYLINDER"
}
},
"someBoolean": {
"title": "someBoolean",
"type": "boolean",
"defaultValue": 1,
"section": "",
"order": 3,
"localization": 0,
"options": {}
},
"someInt": {
"title": "someInt",
"type": "int32",
"defaultValue": 100,
"section": "",
"order": 4,
"localization": 0,
"options": {}
},
"someVector3": {
"title": "someVector3",
"type": "vector3",
"defaultValue": [
0,
1,
0
],
"section": "",
"order": 5,
"localization": 0,
"options": {}
},
"someString": {
"title": "someString",
"type": "string",
"defaultValue": [
"This is a string"
],
"section": "",
"order": 6,
"localization": 0,
"options": {}
},
"mySlider":{
"title": "mySlider",
"type": "int32",
"defaultValue": 10,
"constraints": {
"value_min":1,
"value_max":15,
"value_step":1
}
},
"myVec3Array":{
"title": "myVec3Array",
"type": "vector3[]",
"defaultValue": [
[2,4,6], [1,3,5]
],
"constraints": {
"array_min_length":0,
"array_max_length":3
}
}
}
},
}
Callback Events
A list of the callback events available
// Subscribing to luna:build event – it is going to be fired right after 'load' event of the window.
window.addEventListener('luna:build', function () {
log('Playable is about to start');
});
// Subscribing to luna:unmute event – the playable can play sounds once it is fired.
window.addEventListener('luna:unmute', function () {
log('Playable needs to be unmuted');
});
// Subscribing to luna:mute event – the playable must mute all the sounds once it is fired.
window.addEventListener('luna:mute', function () {
log('Playable needs to be muted');
});
// Subscribing to luna:pause event – the playable must pause rendering and sound playaback.
window.addEventListener('luna:pause', function () {
log('Playable needs to be paused');
});
// Subscribing to luna:pause event – the playable must resume rendering and sound playaback.
window.addEventListener('luna:resume', function () {
log('Playable needs to be resumed');
});
// check if Unity Playworks is defined in global namespace
if ('Luna' in window) {
// it is - nothing to do, the startGame() will be invoked when needed
log('window. Unity Playworks is set - startGame() will be called automatically');
} else {
// it is not - probably a development build, invoke startGame() manually
startGame();
}