Estou construindo um jogo baseado em localização no Unity como uma construção WebGL. O arquivo estava sendo construído antes de eu adicionar minhas alterações de script, mas a entrada de localização não estava funcionando no site (hospedado no itch.io). Então adicionei um arquivo javascript e algumas alterações nos serviços de localização (o script de entrada de localização foi importado da API do Mapbox) usando chatgpt. Agora o arquivo em si não está sendo construído.
arquivo javascript:
var EXPORTED_FUNCTIONS = ['_requestWebGLLocation'];
mergeInto(LibraryManager.library, {
requestWebGLLocation: function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
unityInstance.SendMessage('LocationProviderFactory',
'OnLocationReceived',
position.coords.latitude + ',' +
position.coords.longitude);
},
function(error) {
console.error('Error obtaining location: ', error);
}
);
} else {
console.error('Geolocation is not supported by this browser.');
}
}
})
Código de entrada de localização:
#if !UNITY_EDITOR
#define NOT_UNITY_EDITOR
#endif
namespace Mapbox.Unity.Location
{
using UnityEngine;
using Mapbox.Unity.Map;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
/// <summary>
/// Singleton factory to allow easy access to various LocationProviders.
/// This is meant to be attached to a game object.
/// </summary>
public class LocationProviderFactory : MonoBehaviour
{
[SerializeField]
public AbstractMap mapManager;
[SerializeField]
[Tooltip("Provider using Unity's builtin 'Input.Location' service")]
AbstractLocationProvider _deviceLocationProviderUnity;
[SerializeField]
[Tooltip("Custom native Android location provider. If this is not set above
provider is used")]
DeviceLocationProviderAndroidNative _deviceLocationProviderAndroid;
[SerializeField]
AbstractLocationProvider _editorLocationProvider;
[SerializeField]
AbstractLocationProvider _transformLocationProvider;
[SerializeField]
bool _dontDestroyOnLoad;
[DllImport("__Internal")]
private static extern void requestWebGLLocation();
/// <summary>
/// The singleton instance of this factory.
/// </summary>
private static LocationProviderFactory _instance;
public static LocationProviderFactory Instance
{
get
{
return _instance;
}
private set
{
_instance = value;
}
}
ILocationProvider _defaultLocationProvider;
/// <summary>
/// The default location provider.
/// Outside of the editor, this will be a <see
cref="T:Mapbox.Unity.Location.DeviceLocationProvider"/>.
/// In the Unity editor, this will be an <see
cref="T:Mapbox.Unity.Location.EditorLocationProvider"/>
/// </summary>
/// <example>
/// Fetch location to set a transform's position:
/// <code>
/// void Update()
/// {
/// var locationProvider =
LocationProviderFactory.Instance.DefaultLocationProvider;
/// transform.position =
Conversions.GeoToWorldPosition(locationProvider.Location,
///
MapController.ReferenceTileRect.Center,
///
MapController.WorldScaleFactor).ToVector3xz();
/// }
/// </code>
/// </example>
public ILocationProvider DefaultLocationProvider
{
get
{
return _defaultLocationProvider;
}
set
{
_defaultLocationProvider = value;
}
}
/// <summary>
/// Returns the serialized <see
cref="T:Mapbox.Unity.Location.TransformLocationProvider"/>.
/// </summary>
public ILocationProvider TransformLocationProvider
{
get
{
return _transformLocationProvider;
}
}
/// <summary>
/// Returns the serialized <see
cref="T:Mapbox.Unity.Location.EditorLocationProvider"/>.
/// </summary>
public ILocationProvider EditorLocationProvider
{
get
{
return _editorLocationProvider;
}
}
/// <summary>
/// Returns the serialized <see
cref="T:Mapbox.Unity.Location.DeviceLocationProvider"/>
/// </summary>
public ILocationProvider DeviceLocationProvider
{
get
{
return _deviceLocationProviderUnity;
}
}
/// <summary>
/// Create singleton instance and inject the DefaultLocationProvider upon
Initialization of this component.
/// </summary>
protected virtual void Awake()
{
if (Instance != null)
{
DestroyImmediate(gameObject);
return;
}
Instance = this;
if (_dontDestroyOnLoad)
{
DontDestroyOnLoad(gameObject);
}
InjectEditorLocationProvider();
InjectDeviceLocationProvider();
}
/// <summary>
/// Injects the editor location provider.
/// Depending on the platform, this method and calls to it will be stripped
during compile.
/// </summary>
[System.Diagnostics.Conditional("UNITY_EDITOR")]
void InjectEditorLocationProvider()
{
Debug.LogFormat("LocationProviderFactory: Injected EDITOR Location Provider
- {0}", _editorLocationProvider.GetType());
DefaultLocationProvider = _editorLocationProvider;
}
/// <summary>
/// Injects the device location provider.
/// Depending on the platform, this method and calls to it will be stripped
during compile.
/// </summary>
[System.Diagnostics.Conditional("NOT_UNITY_EDITOR")]
void InjectDeviceLocationProvider()
{
if (Application.platform == RuntimePlatform.WebGLPlayer)
{
Debug.Log("Using WebGL Geolocation.");
requestWebGLLocation();
}
else
{
int AndroidApiVersion = 0;
var regex = new Regex(@"(?<=API-)-?\d+");
Match match = regex.Match(SystemInfo.operatingSystem);
if (match.Success) { int.TryParse(match.Groups[0].Value, out
AndroidApiVersion); }
Debug.LogFormat("{0} => API version: {1}", SystemInfo.operatingSystem,
AndroidApiVersion);
if (Application.platform == RuntimePlatform.Android &&
AndroidApiVersion >= 24)
{
DefaultLocationProvider = _deviceLocationProviderAndroid;
}
else
{
DefaultLocationProvider = _deviceLocationProviderUnity;
}
}
}
public void OnLocationReceived(string locationData)
{
string[] coordinates = locationData.Split(',');
if (coordinates.Length == 2)
{
float latitude = float.Parse(coordinates[0]);
float longitude = float.Parse(coordinates[1]);
Debug.Log($"WebGL Location Received: Latitude: {latitude}, Longitude:
{longitude}");
// You can further process this location data as required
}
}
}
}
Erros de compilação:
Library\Bee\artifacts\WebGL\build\debug_WebGL_wasm\build.js: símbolo indefinido: requestWebGLLocation (referenciado pelo código C/C++ compilado de nível superior) UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
Library\Bee\artifacts\WebGL\build\debug_WebGL_wasm\build.js: Abortando a compilação devido a erros anteriores UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
Falha na criação de Library\Bee\artifacts\WebGL\build\debug_WebGL_wasm\build.js com saída: erro: símbolo indefinido: requestWebGLLocation (referenciado pelo código C/C++ compilado de nível superior) aviso: Link
-s LLD_REPORT_UNDEFINED
para obter mais informações sobre símbolos indefinidos aviso: Para desabilitar erros para símbolos indefinidos, use-s ERROR_ON_UNDEFINED_SYMBOLS=0
aviso: _requestWebGLLocation pode precisar ser adicionado a EXPORTED_FUNCTIONS se chegar de uma biblioteca do sistema Erro: Abortando a compilação devido a erros anteriores emcc: erro: '"C:/Program Files/Unity/Hub/Editor/2022.3.46f1/Editor/Data/PlaybackEngines/WebGLSupport/BuildTools/Emscripten/node/node.exe" "C:\Program Arquivos\Unity\Hub\Editor\2022.3.46f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\src\compiler.js" C:\Users\Nifty\AppData\Local\Temp\tmpmbvsgucj.json' falhou (retornou 1) UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
tl;dr: Altere o tipo de arquivo de
.js
para.jslib
O erro em si é simples: o
_requestWebGLLocation
método/função está faltando no lado do JavaScript.Você disse que seu arquivo é um
.js
arquivo normal simples. O Unity tratará este basicamente como qualquer outro asset de arquivo de texto e o descartará, pois ele não é referenciado em lugar nenhum.Para que o processo de construção do Unity WebGL realmente o reconheça como um plug-in e inclua seu código JavaScript no webassembly, ele precisa ser um
.jslib
arquivo de plug-in adequado!Veja https://docs.unity3d.com/Manual/web-interacting-browser-js.html
O
não deveria ser necessário na verdade
Além disso, em vez de usar,
SendMessage
você pode passar um retorno de chamada e chamá-lo diretamente, o que acho muito mais limpo e menos sujeito a erros, além de ser mais eficiente, pois você passa diretamente o ponteiro do método em vez de fazer o mecanismo procurar o objeto e o método correspondentes pelo nome.Veja https://docs.unity3d.com/Manual/web-interacting-browser-example.html