我正在建立一个基于位置的游戏,有点像口袋妖怪去。 我正在Android手机上阅读该位置没有任何问题,但是当我在Unity编辑器中进行开发时我无法获取任何位置数据,因为在编辑器中Input.location.isEnabledByUser为false
可以模拟/硬编码一个位置,这样我就可以在不部署到手机的情况下进行尝试。
我试着像这样硬编码:
LocationInfo ReadLocation(){
#if UNITY_EDITOR
var location = new LocationInfo();
location.latitude = 59.000f;
location.longitude = 18.000f;
location.altitude= 0.0f;
location.horizontalAccuracy = 5.0f;
location.verticalAccuracy = 5.0f;
return location;
#elif
return Input.location.lastData;
#endif
}
但该位置的所有属性都是只读的,因此我收到了编译错误。 有没有办法在编辑器中启用位置服务,或硬编码位置?
答案 0 :(得分:3)
有没有办法在编辑器中启用位置服务,或者硬编码 位置?
这是Unity Remote成立的原因之一。设置Unity Remote,然后将移动设备连接到编辑器。您现在可以从编辑器中获得真实的位置。
但该位置的所有属性都是只读的
如果你真的想开发一种模拟位置的方法,你必须放弃Unity的LocationInfo
结构。制作您自己的自定义LocationInfo
并将其命名为LocationInfoExt
。 Ext is = Extended。
对LocationService
执行同样的操作,然后将官方LocationService
包装到自定义LocationServiceExt
类中。您可以使用LocationServiceExt
来决定是否应该使用LocationInfoExt
来模拟位置,或者在内部使用LocationInfo
来模拟位置来提供结果。
在下面的示例中,官方LocationService
,LocationInfo
和LocationServiceStatus
类/结构/枚举已替换为LocationServiceExt
,LocationInfoExt
和{{1 }}。它们还具有相同的功能和属性。唯一的区别是你可以将true / false传递给LocationServiceStatusExt
的构造函数,以便在编辑器中使用它。
LocationServiceExt
包装类:
创建一个名为LocationServiceExt
的类,然后将下面的代码复制到其中:
它具有原始LocationServiceExt
类的所有功能和属性。
LocationService
<强>用法强>:
创建模拟位置
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class LocationServiceExt
{
private LocationService realLocation;
private bool useMockLocation = false;
private LocationInfoExt mockedLastData;
private LocationServiceStatusExt mockedStatus;
private bool mIsEnabledByUser = false;
public LocationServiceExt(bool mockLocation = false)
{
this.useMockLocation = mockLocation;
if (mockLocation)
{
mIsEnabledByUser = true;
mockedLastData = getMockLocation();
}
else
{
realLocation = new LocationService();
}
}
public bool isEnabledByUser
{
//realLocation.isEnabledByUser seems to be failing on Android. Input.location.isEnabledByUser is the fix
get { return useMockLocation ? mIsEnabledByUser : Input.location.isEnabledByUser; }
set { mIsEnabledByUser = value; }
}
public LocationInfoExt lastData
{
get { return useMockLocation ? mockedLastData : getRealLocation(); }
set { mockedLastData = value; }
}
public LocationServiceStatusExt status
{
get { return useMockLocation ? mockedStatus : getRealStatus(); }
set { mockedStatus = value; }
}
public void Start()
{
if (useMockLocation)
{
mockedStatus = LocationServiceStatusExt.Running;
}
else
{
realLocation.Start();
}
}
public void Start(float desiredAccuracyInMeters)
{
if (useMockLocation)
{
mockedStatus = LocationServiceStatusExt.Running;
}
else
{
realLocation.Start(desiredAccuracyInMeters);
}
}
public void Start(float desiredAccuracyInMeters, float updateDistanceInMeters)
{
if (useMockLocation)
{
mockedStatus = LocationServiceStatusExt.Running;
}
else
{
realLocation.Start(desiredAccuracyInMeters, updateDistanceInMeters);
}
}
public void Stop()
{
if (useMockLocation)
{
mockedStatus = LocationServiceStatusExt.Stopped;
}
else
{
realLocation.Stop();
}
}
//Predefined Location. You always override this by overriding lastData from another class
private LocationInfoExt getMockLocation()
{
LocationInfoExt location = new LocationInfoExt();
location.latitude = 59.000f;
location.longitude = 18.000f;
location.altitude = 0.0f;
location.horizontalAccuracy = 5.0f;
location.verticalAccuracy = 5.0f;
location.timestamp = 0f;
return location;
}
private LocationInfoExt getRealLocation()
{
if (realLocation == null)
return new LocationInfoExt();
LocationInfo realLoc = realLocation.lastData;
LocationInfoExt location = new LocationInfoExt();
location.latitude = realLoc.latitude;
location.longitude = realLoc.longitude;
location.altitude = realLoc.altitude;
location.horizontalAccuracy = realLoc.horizontalAccuracy;
location.verticalAccuracy = realLoc.verticalAccuracy;
location.timestamp = realLoc.timestamp;
return location;
}
private LocationServiceStatusExt getRealStatus()
{
LocationServiceStatus realStatus = realLocation.status;
LocationServiceStatusExt stats = LocationServiceStatusExt.Stopped;
if (realStatus == LocationServiceStatus.Stopped)
stats = LocationServiceStatusExt.Stopped;
if (realStatus == LocationServiceStatus.Initializing)
stats = LocationServiceStatusExt.Initializing;
if (realStatus == LocationServiceStatus.Running)
stats = LocationServiceStatusExt.Running;
if (realStatus == LocationServiceStatus.Failed)
stats = LocationServiceStatusExt.Failed;
return stats;
}
}
public struct LocationInfoExt
{
public float altitude { get; set; }
public float horizontalAccuracy { get; set; }
public float latitude { get; set; }
public float longitude { get; set; }
public double timestamp { get; set; }
public float verticalAccuracy { get; set; }
}
public enum LocationServiceStatusExt
{
Stopped = 0,
Initializing = 1,
Running = 2,
Failed = 3,
}
创建一个真实的位置
LocationServiceExt locationServiceExt = new LocationServiceExt(true);
稍后在
修改位置LocationServiceExt locationServiceExt = new LocationServiceExt(false);
来自Unity Doc的完整移植工作示例。
LocationInfoExt locInfo = new LocationInfoExt();
locInfo.latitude = 59.000f;
locInfo.longitude = 18.000f;
locInfo.altitude = -3.0f; //0.0f;
locInfo.horizontalAccuracy = 5.0f;
locInfo.verticalAccuracy = 5.0f;
locationServiceExt.lastData = locInfo; //Apply the location change
答案 1 :(得分:1)
要遵循的步骤:
首先,你需要开始GPS呼叫:
Input.location.Start();
“start”需要一些时间来初始化所有需要的进程,因此您可以这样做:
IEnumerator InitLocationTracker()
{
// Start service before querying location
Input.location.Start();
// Wait until service initializes
if (true == disableGPSMode)
{
//delegate to call again "InitLocationTracker"
if (null != OnRetryLocation)
{
OnRetryLocation ();
}
//variable to check the location available
isLocationAvailable = false;
yield return null;
}
// I chose 20s to retry the call
int maxWait = 20;
while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
{
// Service didn't initialize in 20 seconds
if (maxWait < 1)
{
Debug.Log("LocationTracker: Timed out");
//GameObject to show error text
errorText.text = "LocationTracker: Timed out";
errorPanel.SetActive(true);
//delegate to call again "InitLocationTracker"
if (null != OnRetryLocation)
{
isLocationAvailable = false;
OnRetryLocation ();
yield break;
}
}
yield return new WaitForSeconds(1f);
maxWait--;
}
// Connection has failed
if (Input.location.status == LocationServiceStatus.Failed)
{
Debug.Log("LocationTracker: Unable to determine device location");
errorText.text = "LocationTracker: Unable to determine device location";
errorPanel.SetActive(true);
if (null != OnRetryLocation)
{
OnRetryLocation ();
}
isLocationAvailable = false;
}
else
{
Debug.Log("LocationTracker Location: " + current_lat + " " + current_lon + " " + Input.location.lastData.timestamp);
isLocationAvailable = true;
StartCoroutine(TrackLocation());
}
}
然后您可以调用并使用位置数据调用:
private float current_lat;
private float current_lon;
current_lat = Input.location.lastData.latitude;
current_lon = Input.location.lastData.longitude;
但是我会建议你调用一个协程并进行无限循环来检查你是否随时都有GPS信号。伪代码可能是这样的:
IEnumerator TrackLocation()
{
while (true)
{
//5 seconds for example
yield return new WaitForSeconds (5f);
if (Input.location.status == LocationServiceStatus.Running)
{
//Get the location data here
}
}
}
最后一点,如果您需要某些点的GPS数据,您可以将协程移动到您需要的区域。由您决定如何编程GPS检查和数据使用。
资源链接(来自Unity文档)