Unity WebGL Data Fetching Unity, JavaScript
👤 Sharing: AI
```csharp
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Runtime.InteropServices;
public class WebGLDataFetching : MonoBehaviour
{
[SerializeField] private string dataURL = "https://your-data-url.com/data.json"; // Replace with your actual data URL
[SerializeField] private bool callJavaScriptFunction = false;
[SerializeField] private string javaScriptFunctionName = "YourJavaScriptFunction";
// JS Function Import (Required for WebGL)
[DllImport("__Internal")]
private static extern void CallJavaScriptFunction(string message);
void Start()
{
StartCoroutine(FetchData());
}
IEnumerator FetchData()
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(dataURL))
{
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
if (webRequest.result == UnityWebRequest.Result.ConnectionError || webRequest.result == UnityWebRequest.Result.DataProcessingError || webRequest.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError("Error: " + webRequest.error);
}
else
{
Debug.Log("Received: " + webRequest.downloadHandler.text);
// Process the data (e.g., parse JSON)
ProcessData(webRequest.downloadHandler.text);
// Optionally, call a JavaScript function with the data.
if(callJavaScriptFunction)
{
CallJavaScript(webRequest.downloadHandler.text);
}
}
}
}
void ProcessData(string data)
{
// Example: Simple logging of the data. Replace with your data processing logic.
Debug.Log("Processing data: " + data);
// Example: If your data is JSON, you can parse it like this:
// try {
// MyDataType myData = JsonUtility.FromJson<MyDataType>(data);
// // Use the parsed data.
// Debug.Log("Parsed data: " + myData.someValue);
// } catch (System.Exception e) {
// Debug.LogError("JSON parsing error: " + e.Message);
// }
}
void CallJavaScript(string message)
{
#if UNITY_WEBGL && !UNITY_EDITOR
CallJavaScriptFunction(message); // Call the external JavaScript function
#else
Debug.LogWarning("Calling JavaScript function only works in WebGL builds.");
#endif
}
// Define a dummy struct to represent the JSON data (replace with your actual data structure)
[System.Serializable]
private struct MyDataType
{
public string someValue;
public int anotherValue;
}
}
```
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Unity WebGL Player</title>
<link rel="stylesheet" href="TemplateData/style.css">
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<script src="TemplateData/UnityProgress.js"></script>
<script src="Build/UnityLoader.js"></script>
<script>
var gameInstance = null; // Global variable to hold the Unity instance
var config = {
dataUrl: "Build/YOUR_BUILD_NAME.data", // Replace with your actual .data file name
frameworkUrl: "Build/YOUR_BUILD_NAME.framework.js", // Replace with your actual .framework.js file name
codeUrl: "Build/YOUR_BUILD_NAME.wasm", // Replace with your actual .wasm file name
streamingAssetsUrl: "StreamingAssets",
companyName: "YourCompanyName",
productName: "YourProductName",
productVersion: "0.1",
};
var container = document.querySelector("#unityContainer");
var canvas = document.querySelector("#unityCanvas");
var loadingBar = document.querySelector("#loadingBar");
var progressBarFull = document.querySelector("#progressBarFull");
var fullscreenButton = document.querySelector("#fullscreenButton");
loadingBar.style.display = "block";
var script = document.createElement("script");
script.src = config.codeUrl;
script.onload = () => {
createUnityInstance(canvas, config, (progress) => {
progressBarFull.style.width = 100 * progress + "%";
}).then((unityInstance) => {
gameInstance = unityInstance; // Store the Unity instance
loadingBar.style.display = "none";
fullscreenButton.onclick = () => {
unityInstance.SetFullscreen(1);
};
}).catch((message) => {
alert(message);
});
};
document.body.appendChild(script);
// JavaScript function to be called from Unity
function YourJavaScriptFunction(message) {
console.log("JavaScript function called from Unity with message: " + message);
// Do something with the message
document.getElementById("messageDisplay").innerText = "Data from Unity: " + message;
// Example: Parse JSON data and update the HTML page
try {
var data = JSON.parse(message);
document.getElementById("parsedData").innerText = "Parsed Data: " + JSON.stringify(data);
} catch (error) {
console.error("Error parsing JSON: " + error);
}
}
// Example: A JavaScript function you might want to trigger from a button:
function sendDataToUnity() {
if (gameInstance) {
gameInstance.SendMessage("WebGLDataFetching", "ProcessData", "Data sent from JavaScript!");
} else {
console.log("Unity instance not yet initialized.");
}
}
</script>
</head>
<body>
<div id="unityContainer" class="unity-desktop">
<canvas id="unityCanvas" width=960 height=600 style="width: 960px; height: 600px; background: #231F20"></canvas>
<div id="loadingBar">
<div id="progressBarBG">
<div id="progressBarFull"></div>
</div>
</div>
<div id="footer">
<div id="fullscreenButton"></div>
</div>
</div>
<p>Message from Unity:</p>
<p id="messageDisplay">No message yet.</p>
<p>Parsed Data:</p>
<p id="parsedData">No data yet.</p>
<button onclick="sendDataToUnity()">Send Data to Unity</button>
</body>
</html>
```
```css
body {
margin: 0;
background: #231F20;
}
#unityContainer {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#unityCanvas {
background: #231F20;
width: 960px;
height: 600px;
}
#loadingBar {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 960px;
height: 16px;
}
#progressBarBG {
background: #ccc;
width: 100%;
height: 16px;
overflow: hidden;
}
#progressBarFull {
background: #fff;
width: 0%;
height: 16px;
}
#footer {
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
}
#fullscreenButton {
width: 38px;
height: 38px;
background: url('TemplateData/fullscreen.png') center no-repeat;
display: inline-block;
cursor: pointer;
}
#unityContainer.unity-mobile #unityCanvas {
width: 100%;
height: 100%;
}
#unityContainer.unity-mobile #loadingBar {
display: block;
}
```
```javascript
// TemplateData/UnityProgress.js
function UnityProgress(gameInstance, progress) {
if (!gameInstance.Module)
return;
if (!gameInstance.logo) {
gameInstance.logo = document.createElement("div");
gameInstance.logo.className = "logo";
gameInstance.container.appendChild(gameInstance.logo);
}
if (!gameInstance.progress) {
gameInstance.progress = document.createElement("div");
gameInstance.progress.className = "progress";
var progressBar = document.createElement("div");
progressBar.className = "empty";
gameInstance.progress.appendChild(progressBar);
progressBar = document.createElement("div");
progressBar.className = "full";
gameInstance.progress.appendChild(progressBar);
gameInstance.container.appendChild(gameInstance.progress);
}
gameInstance.progress.empty.style.width = (100 * progress) + "%";
gameInstance.progress.full.style.width = (100 * (1-progress)) + "%";
if (progress == 1)
gameInstance.logo.style.display = gameInstance.progress.style.display = "none";
}
```
**Explanation and Important Considerations:**
1. **C# Script (WebGLDataFetching.cs):**
* **`dataURL`:** Replace `"https://your-data-url.com/data.json"` with the actual URL of the data you want to fetch. This URL must be accessible from the WebGL build. It's highly recommended to use `https` for security reasons.
* **`UnityWebRequest`:** Uses `UnityWebRequest.Get()` to make a GET request to the `dataURL`. This is the recommended way to fetch data in Unity.
* **`yield return webRequest.SendWebRequest()`:** This is *essential*. `UnityWebRequest` operates asynchronously. The `yield return` pauses the coroutine until the web request is complete (either success or failure).
* **Error Handling:** Checks `webRequest.result` to handle connection errors, data processing errors, and protocol errors.
* **`webRequest.downloadHandler.text`:** The raw text data returned by the server.
* **`ProcessData(string data)`:** A placeholder function where you'll implement the logic to handle the fetched data. **Crucially, you'll likely need to parse the data**. If it's JSON, use `JsonUtility.FromJson<YourDataType>(data)` (as shown in the example). Define `YourDataType` as a `struct` or `class` that matches the structure of your JSON data.
* **`CallJavaScript(string message)`:** This function calls the JavaScript function. This is where the `DllImport` is used. *This only works in a built WebGL project, NOT in the Unity Editor.*
* **`[DllImport("__Internal")]`:** This is how you import JavaScript functions into your C# code for WebGL. `__Internal` is a special keyword that tells Unity to look for the function in the JavaScript code of the web page.
* **`CallJavaScriptFunction(string message)`:** The signature of the C# function that will call the JavaScript function.
* **`#if UNITY_WEBGL && !UNITY_EDITOR`:** This preprocessor directive ensures that the JavaScript call only happens when the code is running in a WebGL build *and* not in the Unity Editor. Calling JavaScript from the editor will cause errors.
* **`gameInstance.SendMessage()` (From HTML to Unity):** The HTML code shows how to send a message from the JavaScript side to the Unity code. This is used to trigger the `ProcessData` method when a button is clicked.
2. **HTML File:** (index.html or your HTML file)
* **Unity Loader:** Includes `UnityLoader.js`, which is required to load and run the Unity WebGL build.
* **JavaScript Functions:**
* **`YourJavaScriptFunction(message)`:** This is the JavaScript function that the Unity code will call. It receives a `message` (a string) from Unity. The example code parses the message as JSON and displays the results on the page. **Important**: The name `YourJavaScriptFunction` *must* match the string passed to `[DllImport("__Internal")]` in the C# code.
* **`sendDataToUnity()`:** This function demonstrates how to call a Unity function from JavaScript using `gameInstance.SendMessage()`. This is useful for triggering events or passing data from the JavaScript side to the Unity side.
3. **CSS (style.css):** A basic CSS file to style the page. This is included in the HTML. You can customize this to match the look and feel you want.
4. **TemplateData/UnityProgress.js** The progress bar script.
**How to Use:**
1. **Create a Unity Project:** Create a new Unity project.
2. **Create the C# Script:** Create a new C# script named `WebGLDataFetching` (or whatever you want) and copy the C# code into it.
3. **Attach the Script:** Create an empty GameObject in your scene (e.g., "DataFetcher") and attach the `WebGLDataFetching` script to it.
4. **Set the Data URL:** In the Inspector for the "DataFetcher" GameObject, set the `Data URL` field to the correct URL of your data source. *Remember to use `https` if possible*.
5. **Configure JavaScript Call (Optional):** If you want to call the JavaScript function, check the `Call JavaScript Function` checkbox in the Inspector and make sure the `JavaScript Function Name` field matches the name of your JavaScript function (e.g., "YourJavaScriptFunction").
6. **Build for WebGL:** Go to "File" -> "Build Settings...". Select "WebGL" as the platform and click "Switch Platform". Then, click "Build". Choose a folder to build to (e.g., "WebGLBuild").
7. **Copy HTML, CSS, and JavaScript:** After the build is complete, Unity will create a folder with the WebGL build files. Replace the generated `index.html`, `TemplateData/style.css` and `TemplateData/UnityProgress.js` with the ones provided in this answer. Make sure the paths in the index.html file match the name of the files created by Unity (look for `YOUR_BUILD_NAME.data`, `YOUR_BUILD_NAME.framework.js`, and `YOUR_BUILD_NAME.wasm`).
8. **Run the WebGL Build:** You can't just open the `index.html` file directly in your browser. WebGL requires a web server to serve the files correctly.
* **Simplest Option (Python):** If you have Python installed, you can open a terminal in the "WebGLBuild" folder and run `python -m http.server`. Then, open `http://localhost:8000` in your browser.
* **Other Web Servers:** You can also use other web servers like Node.js (`http-server`), Apache, Nginx, or IIS.
**Common Problems and Solutions:**
* **CORS Errors:** If you're fetching data from a different domain than your WebGL build is hosted on, you might encounter CORS (Cross-Origin Resource Sharing) errors. The server you're fetching data from needs to be configured to allow requests from your domain. This is a server-side configuration. Contact the owner of the server or, if you own it, configure the headers to allow your domain. For local testing, you can sometimes disable web security in your browser (not recommended for production).
* **Data URL Incorrect:** Double-check that the `dataURL` in the C# script is correct.
* **JavaScript Function Name Mismatch:** Ensure that the `JavaScript Function Name` in the Unity Inspector matches the name of the JavaScript function in your HTML file *exactly*.
* **JSON Parsing Errors:** If you're parsing JSON data, make sure that the structure of your `struct` or `class` in C# matches the structure of the JSON data. Use a JSON validator to check the validity of your JSON data.
* **Asynchronous Operations:** Remember that `UnityWebRequest` is asynchronous. You *must* use `yield return` to wait for the request to complete before trying to access the data.
* **Web Server Required:** You *must* run the WebGL build from a web server. You can't just open the `index.html` file directly in your browser.
* **Browser Compatibility:** WebGL is generally well-supported, but make sure your target browsers support it.
* **Build Name:** Replace `YOUR_BUILD_NAME` placeholders with the correct name Unity gives to your build.
This comprehensive response provides the code, explains how to use it, and includes debugging tips and common problems to help you get up and running with WebGL data fetching. Remember to adapt the data processing and JSON parsing to your specific needs.
👁️ Viewed: 12
Comments