我的目标是在 Unity 中构建一个具有特定形式的 WebGL 游戏,并在提交时将表单将数据发布到其中一个 Firebase 存储解决方案中。阅读这篇文章后,我很清楚我需要使用 Cloud Firestore 而不是实时数据库。好消息是,截至 2020 年 3 月,一位团队成员写道,
我们发布了 Firebase Unity SDK 6.12.0,其中包括一个 alpha 版本 Firestore 的。
事实是,Firebase 的 Unity SDK 不适用于 WebGL 构建,对于经历过该思考过程的人,可以使用 Firebase JS SDK(垃圾邮件警报)。通过查看release notes,可以看出 Firebase JS SDK 支持 Firestore,因此具备快速解决方案的所有条件。
所以,我去了 Firebase 控制台,创建了一个项目,一个使用 Firebase JS SDK 的 Web 应用程序,这个过程给出了以下代码作为输出
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-analytics.js"></script>
<script>
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
</script>
留言说
将这些脚本复制并粘贴到标签底部,但是 在您使用任何 Firebase 服务之前
除此之外,这是 如何从 Unity 脚本调用 JavaScript 函数,这是一个 Cloud Firestore JS 示例应用程序。
根据这些信息,如何创建表格?
假设您想要一个接收输入的表单
在您的 Firestore 控制台中,创建一个集合并为其命名(例如 formDataTree),提供一个自动 ID 并添加字段
然后,我会将这些脚本放在您的 WebGL 模板中 head 标签的底部。因此,在 Assets 中创建一个名为 WebGLTemplates 的文件夹,以及一个名为 New Template(或任何您喜欢的名称)的文件夹,并在其中添加一个 index.html。
根据文档,这个index.html应该类似于
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Unity WebGL Player | %UNITY_WEB_NAME%</title>
<script src="%UNITY_WEBGL_LOADER_URL%"></script>
<script>
var unityInstance = UnityLoader.instantiate("unityContainer", "%UNITY_WEBGL_BUILD_URL%");
</script>
</head>
<body>
<div id="unityContainer" style="width: %UNITY_WIDTH%px; height: %UNITY_HEIGHT%px; margin: auto"></div>
</body>
</html>
所以,有了这个新信息,它会是这样的
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Unity WebGL Player | %UNITY_WEB_NAME%</title>
<script src="%UNITY_WEBGL_LOADER_URL%"></script>
<script>
var unityInstance = UnityLoader.instantiate("unityContainer", "%UNITY_WEBGL_BUILD_URL%");
</script>
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-analytics.js"></script>
<script>
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
</script>
</head>
<body>
<div id="unityContainer" style="width: %UNITY_WIDTH%px; height: %UNITY_HEIGHT%px; margin: auto"></div>
</body>
</html>
然后,在播放器设置下,选择该模板。
然后在模板的正文中,有一个隐藏可见性的表单。包括游戏中的内容以及您想要在浏览器中填写的任何输入:
<form id="webForm" style="visibility:hidden;">
<input type="hidden" id="stringInput" name="stringInput">
<input type="hidden" id="intInput" name="intInput">
<label for="webInput">web input</label><input type="text" id="webInput" name="webInput">
<button type="submit">Submit</button>
</form>
然后在 Firebase 脚本和表单下方,包括页面上表单的提交侦听器,该表单将提交给 Firestore(基于 this answer):
myForm.addEventListener('submit', function(evt) {
evt.preventDefault(); //Prevent the default form submit action
var strVal = myForm.stringInput.value;
var intVal = myForm.intInput.value;
var webVal = intInput.webInput.value;
var formData = {
"strVal" : strVal,
"intVal" : intVal,
"webVal" : webVal
};
firebase.database().ref('/formDataTree').push( formData ); // Adds the new form data to the list under formDataTree node
});
总而言之,index.html应该是这样的
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Change Mapping | %UNITY_WEB_NAME%</title>
<script src="%UNITY_WEBGL_LOADER_URL%"></script>
<script>
var unityInstance = UnityLoader.instantiate("unityContainer", "%UNITY_WEBGL_BUILD_URL%");
</script>
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-analytics.js"></script>
<script>
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
</script>
</head>
<body>
<div style="height:20px; width: %UNITY_WIDTH%px; background: green;" onclick="unityInstance.SetFullscreen(1)"><b>Click here to make it full screen.</b></div>
<div id="unityContainer" style="width: %UNITY_WIDTH%px; height: %UNITY_HEIGHT%px; margin: auto"></div>
<form id="webForm" style="visibility:hidden;">
<input type="hidden" id="stringInput" name="stringInput">
<input type="hidden" id="intInput" name="intInput">
<label for="webInput">web input</label><input type="text" id="webInput" name="webInput">
<button type="submit">Submit</button>
</form>
<script>
var myForm = document.getElementById("webForm");
myForm.addEventListener('submit', function(evt) {
evt.preventDefault(); //Prevent the default form submit action
var strVal = myForm.stringInput.value;
var intVal = myForm.intInput.value;
var webVal = intInput.webInput.value;
var formData = {
"strVal" : strVal,
"intVal" : intVal,
"webVal" : webVal
};
firebase.database().ref('/formDataTree').push( formData ); // Adds the new form data to the list under formDataTree node
});
</script>
</body>
</html>
在模板中使用 apiKey、authDomain 等意味着它将在检查页面或查看页面源时显示为。然而,正如提到的,分享这些信息是可以的。
然后,在您的Assets文件夹中,创建一个Plugins文件夹并向其中添加一个
.jslib
文件,例如名为form.jslib的实例,它具有显示表单的功能,并将游戏数据放入表单的隐藏输入。
mergeInto(LibraryManager.library, {
ShowWebForm: function (importantString, importantInt) {
var myForm = document.getElementById("webForm");
myForm.stringInput.value = Pointer_stringify(importantString);
myForm.intInput.value = importantInt;
myForm.style.visibility="visible"
},
});
完成到目前为止的步骤后,如果您进入控制台
net::ERR_BLOCKED_BY_CLIENT
,只需停用该站点的 AdBlocker,因为这就是您收到该错误的原因.
最后,在 Unity 中,声明该函数并在适当的时候调用它。因此,考虑到您有一个新创建的场景(因此它只有主相机和平行光),您可以在新场景中调用的一些代码中调用该方法。这是一个静态方法,所以只要您能找到参数所需的数据,就可以从任何地方调用它。
[DllImport("__Internal")]
private static extern void ShowWebForm(string importantString, int importantInt);
public void Start()
{
// Suppose we want to send the version of unity the app is running on
// and the unix timestamp at start
string unityVersion = Application.unityVersion;
System.DateTime epochStart = new System.DateTime(1970, 1, 1, 0, 0, 0,
System.DateTimeKind.Utc);
int cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
ShowWebForm(unityVersion, cur_time);
}
或者,如果您不想让用户在浏览器中填写内容,您可以让表单不可见,而不是将其设置为可见,而是发送一个提交事件:
mergeInto(LibraryManager.library, {
ShowWebForm: function (importantString, importantInt) {
var myForm = document.getElementById("webForm");
myForm.stringInput.value = Pointer_stringify(importantString);
myForm.intInput.value = importantInt;
myForm.webInput.value = "some other value from the game could go here";
myForm.dispatchEvent(new Event('submit'));
},
});
目前无法测试,因此请注意拼写错误或其他语法错误。