- Home /
WebGL build callback on tab close or browser quit.
Hello! We're porting a game from android/iOS to WebGL and the problem is that we save player data when appliaction loses focus or pauses via OnAppliacitonPause/Focus. This function gets called in WebGL builds when you switch to another tab or move focus to another part of the page. However if user just closes the tab, there is no callback for us to save his data.
The question is - can the callback on tab close or browser quit can be implemented for WebGL? Im trying to make JS function "onbeforunload" work but no success so far. Any other way to achieve this?
Same here. But it seems Unity $$anonymous$$m's considered it unsolvable.
Yeah, I implemented periodic save feature for that.
Answer by TreyH · Aug 23, 2018 at 05:21 PM
Note: The yellow console warnings are coming from the Unity scene.
It may not work with the native OnApplicationQuit
, but it is possible. You can do this using a custom WebGL Template. Before you start reading, it might be a good idea to glance over the Unity Documentation on Interacting with Browser Scripting.
Setting up your WebGL Template
First, you'll want to create a WebGL template to use for your project. Read through that guide to learn how to create one. Once that's done, you'll have something in a <script>
tag that looks like this:
gameInstance = UnityLoader.instantiate("gameContainer", "%UNITY_WEBGL_BUILD_URL%", {});
You'll use this object to communicate with your Unity Scene, as it can use the well-known SendMessage
function. For now, paste this below that UnityLoader.instantiate
line in your template:
// Callback for the Unity OnClose event
window.onbeforeunload = function(e) {
// These are the messages you're seeing in the gif
console.log("Calling OnClose from Browser!");
gameInstance.SendMessage("OnCloseObject", "OnClose");
// This never shows up correctly for me, but it does prompt
// the player to close their window with a dialogue box
//
var dialogText = "You game has been saved! Would you like to continue unloading the page?";
e.returnValue = dialogText;
return dialogText;
};
As of right now, your Unity's browser will try to call functions in Unity that don't exist yet, so let's set those up now.
Setting up your Scene
In my example, I made a simple object named OnCloseObject
with a single script given below:
using UnityEngine;
using UnityEngine.UI;
public class OnCloseListener : MonoBehaviour
{
public Image backgroundImage;
/// <summary>
/// Called when the Browser is closed.
/// </summary>
public void OnClose()
{
// Uncomment this if you set up Interop
//BrowserJS.Warn("This warning was called from Unity!");
// Randomize the background image color
this.backgroundImage.color = new Color(Random.value, Random.value, Random.value);
}
}
If you don't want to set up the Interop stuff for Unity to speak to the browser, skip the next part.
(Optional) Setting up Interop
Create a folder called Plugins
in your project and add the following as plugins.jslib
:
mergeInto(LibraryManager.library, {
Alert: function (str) {
window.alert(Pointer_stringify(str));
},
Console: function (str) {
console.log(Pointer_stringify(str));
},
Warn: function (str) {
console.warn(Pointer_stringify(str));
},
Error: function (str) {
console.error(Pointer_stringify(str));
}
});
Then, create a new script and paste this:
using System.Runtime.InteropServices;
public class BrowserJS
{
[DllImport("__Internal")]
public static extern void Alert(string str);
[DllImport("__Internal")]
public static extern void Log(string str);
[DllImport("__Internal")]
public static extern void Warn(string str);
[DllImport("__Internal")]
public static extern void Error(string str);
}
Once this is in place and your WebGL build is using your modified Template, you should be ready to go.
There might be some race conditions if your save process is a bit lengthy and the user closes out too quickly? I am sure there are some nuance-y things I am missing here, but this should be enough to get you started.
Additionally, if you're intent on using the existing OnApplicationQuit function bodies, you could trigger something silly like this:
private void TriggerApplicationQuit()
{
// Get every $$anonymous$$onoBehaviour
var allGameObjects = GameObject.FindObjectsOfType<GameObject>();
for (int k=0; k< allGameObjects.Length; k++)
{
allGameObjects[k].Send$$anonymous$$essage("OnApplicationQuit", Send$$anonymous$$essageOptions.DontRequireReceiver);
}
}
WOW!
This is a huge answer for a question that is not relevant to me yet! But thanks a lot, I'll be sure to save it so that I can use it if im going to work with WebGL again.
Your answer
Follow this Question
Related Questions
Interact across browser javascipt and unity webgl 2 Answers
How to send multiple values from browser to unity webgl game? 1 Answer
Webgl - Networked game - process of uploading - errors - questions 0 Answers
IsLoaded function for Browsercommunication? 1 Answer
WebGL - Open URL in new tab? 10 Answers