You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity WebGL构建项目无法通过Mapbox SDK获取浏览器定位服务

Unity WebGL构建项目无法通过Mapbox SDK获取浏览器定位服务

我用Unity导出了一个WebGL应用,添加了JavaScript和C#代码来获取浏览器的定位服务,但启动应用时,虽然弹出了权限请求,应用却无法接收到定位信息。我使用的是Mapbox SDK中的LocationProviderFactory定位服务脚本。

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#定位代码

#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;
    using System.Collections;


    /// <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();
        }

        private void Start()
        {
            StartCoroutine(StartLocationService());
        }

        /// <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
            }
        }

        IEnumerator StartLocationService()
        {
            if (!Input.location.isEnabledByUser)
            {
                Debug.LogError("Location services are not enabled.");
                yield break;
            }

            Input.location.Start();

            int maxWait = 20;
            while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
            {
                yield return new WaitForSeconds(1);
                maxWait--;
            }

            if (maxWait <= 0)
            {
                Debug.LogError("Timed out while initializing location services.");
                yield break;
            }

            if (Input.location.status == LocationServiceStatus.Failed)
            {
                Debug.LogError("Unable to determine device location.");
                yield break;
            }

            Debug.Log($"Location: {Input.location.lastData.latitude}, {Input.location.lastData.longitude}");
        }


    }
}

编辑器错误信息

Location services are not enabled.
UnityEngine.Debug:LogError (object)
Mapbox.Unity.Location.LocationProviderFactory/<StartLocationService>d__26:MoveNext () (at Assets/Mapbox/Unity/Location/LocationProviderFactory.cs:210)
UnityEngine.MonoBehaviour:StartCoroutine (System.Collections.IEnumerator)
Mapbox.Unity.Location.LocationProviderFactory:Start () (at Assets/Mapbox/Unity/Location/LocationProviderFactory.cs:149)
GUI Error: Invalid GUILayout state in  view. Verify that all layout Begin/End calls match
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

备注:内容来源于stack exchange,提问作者NiftyRunner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 13:58:01