首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Unity3D程序在3-5秒后挂起

Unity3D程序在3-5秒后挂起
EN

Stack Overflow用户
提问于 2017-03-12 07:22:49
回答 1查看 160关注 0票数 0

我的代码就在这里:

代码语言:javascript
复制
using UnityEngine;
using Assets.Helpers; //DONT COPY
using System;
using System.Collections;

public class TileManager : MonoBehaviour {
[SerializeField]
private Settings _settings;

[SerializeField]
private Transform target;

[SerializeField]
private Texture2D texture;
private GameObject tile;

[SerializeField]//DONT COPY
private GameObject service;//DONT COPY

private float oldLat = 0f, oldLon = 0f;
private float lat = 0f, lon = 0f;

public PokemonManager pokeManager;

public float getLat {
    get {
        return lat;
    }
}

public float getLon {
    get { 
        return lon;
    }
}

IEnumerator Start()
{
    while (!Input.location.isEnabledByUser) {
        print ("Activate gps");
        yield return new WaitForSeconds (1f);
    }

    Debug.Log ("1");
    Input.location.Start(10f, 5f);

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

    if (maxWait < 1)
    {
        print("Timed out");
        yield break;
    }

    if (Input.location.status == LocationServiceStatus.Failed)
    {
        print("Unable to determine device location");
        yield break;
    }
    else
    {
        print("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp);
    }

    lat = Input.location.lastData.latitude;
    lon = Input.location.lastData.longitude;

    StartCoroutine (loadTiles (_settings.zoom));

    while (Input.location.isEnabledByUser) {

        yield return new WaitForSeconds (1f);           
    }

    yield return StartCoroutine (Start ());
    yield break;
}

public IEnumerator loadTiles(int zoom) {
    int size = _settings.size;
    string key = _settings.key;
    string style = _settings.style;

    lat = Input.location.lastData.latitude;
    lon = Input.location.lastData.longitude;

    string url = String.Format ("https://api.mapbox.com/v4/mapbox.{5}/{0},{1},{2}/{3}x{3}@2x.png?access_token={4}", lon, lat, zoom, size, key, style);

    WWW www = new WWW (url);
    yield return www;

    texture = www.texture;

    if (tile == null) {
        tile = GameObject.CreatePrimitive (PrimitiveType.Plane);
        tile.name = "Tile " + lat + "" + lon;
        tile.transform.localScale = Vector3.one * _settings.scale;
        tile.GetComponent<Renderer> ().material = _settings.material;
        tile.transform.parent = transform;
    }

    if (oldLat != 0 && oldLon != 0) {
        float x, y;
        Vector3 position = Vector3.zero;

        geodeticOffsetInv (lat * Mathf.Deg2Rad, lon * Mathf.Deg2Rad, oldLat * Mathf.Deg2Rad, oldLon * Mathf.Deg2Rad, out x, out y);

        if ((oldLat - lat) < 0 && (oldLon - lon) > 0 || (oldLat - lat) > 0 && (oldLon - lon) < 0) {
            position = new Vector3 (x, .5f, y);
        } else {
            position = new Vector3 (-x, .5f, -y);
        }

        position.x *= 0.300122f;
        position.z *= 0.123043f;

        target.position = position;
        Debug.Log ("called");
        /*float[] ll = px (lat, lon, _settings.zoom);
        float[] oll = px (oldLat, oldLon, _settings.zoom);
        x = ll [0] - oll [0];
        y = ll [0] - oll [0];

        float ps = 10 * _settings.scale / _settings.size;
        x *= ps;
        y *= ps;

        Debug.Log (x + " / " + y);*/
    }

    pokeManager.UpdatePokemonPosition ();

    tile.GetComponent<Renderer> ().material.mainTexture = texture;

    yield return new WaitForSeconds (1f);

    oldLat = lat;
    oldLon = lon;

    while (oldLat == lat && oldLon == lon) {
        lat = Input.location.lastData.latitude;
        lon = Input.location.lastData.longitude;
        yield return new WaitForSeconds (0.5f);
    }

    yield return new WaitUntil ( () => (oldLat != lat || oldLon != lon) );

    yield return StartCoroutine (loadTiles (_settings.zoom));
    yield break;
}

/*float[] px (float lat, float lon, int zoom) {
    float d = (_settings.size / 2 * Mathf.Pow (2, _settings.zoom));
    float f = Mathf.Min(Mathf.Max(Mathf.Sin(Mathf.Deg2Rad * lat), -0.9999f), 0.9999f);
    float x = Mathf.Round(d + lon * (_settings.size / 360 * Mathf.Pow (2, _settings.zoom)));
    float y = Mathf.Round(d + 0.5f * Mathf.Log((1 + f) / (1 - f)) * (-(_settings.size / (2 * Mathf.PI) * Mathf.Pow (2, _settings.zoom))));
    float[] result = new float[2];
    result [0] = x;
    result [1] = y;
    return result;
}*/

//SOURCE: http://stackoverflow.com/questions/4953150/convert-lat-longs-to-x-y-co-ordinates

float GD_semiMajorAxis = 6378137.000000f;
float GD_TranMercB     = 6356752.314245f;
float GD_geocentF      = 0.003352810664f;

void geodeticOffsetInv( float refLat, float refLon,
    float lat,    float lon,
    out float xOffset, out float yOffset )
{
    float a = GD_semiMajorAxis;
    float b = GD_TranMercB;
    float f = GD_geocentF;

    float L = lon - refLon;
    float U1    = Mathf.Atan((1-f) * Mathf.Tan(refLat));
    float U2    = Mathf.Atan((1-f) * Mathf.Tan(lat));
    float sinU1 = Mathf.Sin(U1);
    float cosU1 = Mathf.Cos(U1);
    float sinU2 = Mathf.Sin(U2);
    float cosU2 = Mathf.Cos(U2);

    float lambda = L;
    float lambdaP;
    float sinSigma;
    float sigma;
    float cosSigma;
    float cosSqAlpha;
    float cos2SigmaM;
    float sinLambda;
    float cosLambda;
    float sinAlpha;
    int iterLimit = 100;
    do {
        sinLambda = Mathf.Sin(lambda);
        cosLambda = Mathf.Cos(lambda);
        sinSigma = Mathf.Sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
            (cosU1*sinU2-sinU1*cosU2*cosLambda) *
            (cosU1*sinU2-sinU1*cosU2*cosLambda) );
        if (sinSigma==0)
        {
            xOffset = 0.0f;
            yOffset = 0.0f;
            return ;  // co-incident points
        }
        cosSigma    = sinU1*sinU2 + cosU1*cosU2*cosLambda;
        sigma       = Mathf.Atan2(sinSigma, cosSigma);
        sinAlpha    = cosU1 * cosU2 * sinLambda / sinSigma;
        cosSqAlpha  = 1 - sinAlpha*sinAlpha;
        cos2SigmaM  = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
        if (cos2SigmaM != cos2SigmaM) //isNaN
        {
            cos2SigmaM = 0;  // equatorial line: cosSqAlpha=0 (ยง6)
        }
        float C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
        lambdaP = lambda;
        lambda = L + (1-C) * f * sinAlpha *
            (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
    } while (Mathf.Abs(lambda-lambdaP) > 1e-12 && --iterLimit>0);

    if (iterLimit==0)
    {
        xOffset = 0.0f;
        yOffset = 0.0f;
        return;  // formula failed to converge
    }

    float uSq  = cosSqAlpha * (a*a - b*b) / (b*b);
    float A    = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
    float B    = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
    float deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
        B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
    float s = b*A*(sigma-deltaSigma);

    float bearing = Mathf.Atan2(cosU2*sinLambda,  cosU1*sinU2-sinU1*cosU2*cosLambda);
    xOffset = Mathf.Sin(bearing)*s;
    yOffset = Mathf.Cos(bearing)*s;
}

void Update() {
    service.SetActive (!Input.location.isEnabledByUser);//DONT COPY
    target.position = Vector3.Lerp (target.position, new Vector3 (0,.5f, 0), 2.0f * Time.deltaTime);
    Debug.Log ("lerped");
}

[Serializable]
public class Settings {
    [SerializeField]
    public Vector2 centerPosition;
    [SerializeField]
    public Material material;
    [SerializeField]
    public int zoom = 18;
    [SerializeField]
    public int size = 640;
    [SerializeField]
    public float scale = 1f;
    [SerializeField]
    public int range = 1;
    [SerializeField]
    public string key = "KEY_HERE";
    [SerializeField]
    public string style = "emerald";
}

}

我的代码运行了大约3秒,然后挂起,就像我不能再滑动一样(还有另一个脚本被分配用于滑动)。然后大约再过5秒,我的应用程序就崩溃了。这有什么问题吗?

编辑过的代码

代码语言:javascript
复制
using UnityEngine;
using Assets.Helpers; //DONT COPY
using System;
using System.Collections;

public class TileManager : MonoBehaviour {
[SerializeField]
private Settings _settings;

[SerializeField]
private Transform target;

[SerializeField]
private Texture2D texture;
private GameObject tile;

[SerializeField]//DONT COPY
private GameObject service;//DONT COPY

private float oldLat = 0f, oldLon = 0f;
private float lat = 0f, lon = 0f;

public PokemonManager pokeManager;

public Animator animator;

public float getLat {
    get {
        return lat;
    }
}

public float getLon {
    get { 
        return lon;
    }
}

IEnumerator Start()
{
    //Waiting for user to turn on GPS
    while (!Input.location.isEnabledByUser) {
        print ("Activate gps");
        yield return new WaitForSeconds (1f);
    }

    Input.location.Start(10f, 5f);

    //Waiting for GPS service to work
    int maxWait = 20;
    while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
    {
        yield return new WaitForSeconds(1);
        maxWait--;
    }

    //GPS Service failed to work so break
    //Break - Go out and end the function Start()
    if (maxWait < 1)
    {
        print("Timed out");
        yield break;
    }

    if (Input.location.status == LocationServiceStatus.Failed)
    {
        //GPS Service failed to work so break
        //Break - Go out and end the function Start()
        print("Unable to determine device location");
        yield break;
    }
    else
    {
        print("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp);
    }

    //Set latitude and longitude of user's current location
    lat = Input.location.lastData.latitude;
    lon = Input.location.lastData.longitude;

    //Call this coroutine which is responsible for:
    //1. Loading of the map
    //2. Updating of the map
    //StartCoroutine (loadTiles (_settings.zoom));

    while (Input.location.isEnabledByUser) {
        yield return new WaitForSeconds (1f);           
    }

    yield return null;
    StartCoroutine (Start ());
    yield break;
}

public IEnumerator loadTiles(int zoom) {
    int size = _settings.size;
    string key = _settings.key;
    string style = _settings.style;

    lat = Input.location.lastData.latitude;
    lon = Input.location.lastData.longitude;

    //string url = String.Format ("https://api.mapbox.com/v4/mapbox.{5}/{0},{1},{2}/{3}x{3}@2x.png?access_token={4}", lon, lat, zoom, size, key, style);
    string url = String.Format("https://api.mapbox.com/styles/v1/{5}/static/{0},{1},{2}/{3}x{3}@2x?access_token={4}", lon, lat, zoom, size, key, style);
    WWW www = null;

    www = new WWW (url);
    yield return www;

    texture = www.texture;

    if (tile == null) {
        tile = GameObject.CreatePrimitive (PrimitiveType.Plane);
        tile.name = "Tile " + lat + "" + lon;
        tile.transform.localScale = Vector3.one * _settings.scale;
        tile.GetComponent<Renderer> ().material = _settings.material;
        tile.transform.parent = transform;
    }

    if (oldLat != 0 && oldLon != 0) {
        float x, y;
        Vector3 position = Vector3.zero;

        geodeticOffsetInv (lat * Mathf.Deg2Rad, lon * Mathf.Deg2Rad, oldLat * Mathf.Deg2Rad, oldLon * Mathf.Deg2Rad, out x, out y);

        if ((oldLat - lat) < 0 && (oldLon - lon) > 0 || (oldLat - lat) > 0 && (oldLon - lon) < 0) {
            position = new Vector3 (x, .5f, y);
        } else {
            position = new Vector3 (-x, .5f, -y);
        }

        position.x *= 0.300122f;
        position.z *= 0.123043f;

        target.position = position;
    }

    pokeManager.UpdatePokemonPosition ();

    tile.GetComponent<Renderer> ().material.mainTexture = texture;

    yield return new WaitForSeconds (1f);

    oldLat = lat;
    oldLon = lon;

    while (oldLat == lat && oldLon == lon) {
        lat = Input.location.lastData.latitude;
        lon = Input.location.lastData.longitude;
        yield return new WaitForSeconds (0.5f);
    }

    yield return new WaitUntil ( () => (oldLat != lat || oldLon != lon) );

    yield return null;
    StartCoroutine (loadTiles (_settings.zoom));
    yield break;
}


//SOURCE: http://stackoverflow.com/questions/4953150/convert-lat-longs-to-x-y-co-ordinates

float GD_semiMajorAxis = 6378137.000000f;
float GD_TranMercB     = 6356752.314245f;
float GD_geocentF      = 0.003352810664f;

void geodeticOffsetInv( float refLat, float refLon, float lat, float lon,out float xOffset, out float yOffset)
{
    float a = GD_semiMajorAxis;
    float b = GD_TranMercB;
    float f = GD_geocentF;

    float L = lon - refLon;
    float U1    = Mathf.Atan((1-f) * Mathf.Tan(refLat));
    float U2    = Mathf.Atan((1-f) * Mathf.Tan(lat));
    float sinU1 = Mathf.Sin(U1);
    float cosU1 = Mathf.Cos(U1);
    float sinU2 = Mathf.Sin(U2);
    float cosU2 = Mathf.Cos(U2);

    float lambda = L;
    float lambdaP;
    float sinSigma;
    float sigma;
    float cosSigma;
    float cosSqAlpha;
    float cos2SigmaM;
    float sinLambda;
    float cosLambda;
    float sinAlpha;
    int iterLimit = 100;
    do {
        sinLambda = Mathf.Sin(lambda);
        cosLambda = Mathf.Cos(lambda);
        sinSigma = Mathf.Sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
            (cosU1*sinU2-sinU1*cosU2*cosLambda) *
            (cosU1*sinU2-sinU1*cosU2*cosLambda) );
        if (sinSigma==0)
        {
            xOffset = 0.0f;
            yOffset = 0.0f;
            return ;  // co-incident points
        }
        cosSigma    = sinU1*sinU2 + cosU1*cosU2*cosLambda;
        sigma       = Mathf.Atan2(sinSigma, cosSigma);
        sinAlpha    = cosU1 * cosU2 * sinLambda / sinSigma;
        cosSqAlpha  = 1 - sinAlpha*sinAlpha;
        cos2SigmaM  = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
        if (cos2SigmaM != cos2SigmaM) //isNaN
        {
            cos2SigmaM = 0;  // equatorial line: cosSqAlpha=0 (§6)
        }
        float C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
        lambdaP = lambda;
        lambda = L + (1-C) * f * sinAlpha *
            (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
    } while (Mathf.Abs(lambda-lambdaP) > 1e-12 && --iterLimit>0);

    if (iterLimit==0)
    {
        xOffset = 0.0f;
        yOffset = 0.0f;
        return;  // formula failed to converge
    }

    float uSq  = cosSqAlpha * (a*a - b*b) / (b*b);
    float A    = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
    float B    = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
    float deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
        B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
    float s = b*A*(sigma-deltaSigma);

    float bearing = Mathf.Atan2(cosU2*sinLambda,  cosU1*sinU2-sinU1*cosU2*cosLambda);
    xOffset = Mathf.Sin(bearing)*s;
    yOffset = Mathf.Cos(bearing)*s;
}

void Update() {
    //service.SetActive (!Input.location.isEnabledByUser);//DONT COPY
    target.position = Vector3.Lerp (target.position, new Vector3 (0,.5f, 0), 2.0f * Time.deltaTime);
}

[Serializable]
public class Settings {
    [SerializeField]
    public Vector2 centerPosition;
    [SerializeField]
    public Material material;
    [SerializeField]
    public int zoom = 18;
    [SerializeField]
    public int size = 640;
    [SerializeField]
    public float scale = 1f;
    [SerializeField]
    public int range = 1;
    [SerializeField]
    public string key = "KEY_HERE";
    [SerializeField]
    public string style = "emerald";
}
}
EN

回答 1

Stack Overflow用户

发布于 2017-03-12 08:10:17

你正在进入无限循环。

以下是问题所在:

代码语言:javascript
复制
yield return StartCoroutine (Start ());

当你执行yield return StartCoroutine (Start ())时,它会启动新的协程,然后等待完成旧的协程(这永远不会发生),然后它会在第一个协程运行的时候启动另一个协程。

您在yield return StartCoroutine (Start ())之后拥有的yield break;将不会被调用甚至。您可以通过将Debug.LogWarning("Finished coroutine!");放在该yield break;之后来证明这一点。该Debug.Log消息将永远不会显示。

这里最大的问题是这些协程都没有真正停止。然后他们yield启动另一个,然后等待那个完成,然后启动另一个。正因为如此,您可以轻松地运行数千个协程。

要解决这个问题,必须做两件事

1.Remove yield return,所以协程实际上可以退出。

因此,请使用StartCoroutine (Start ());而不是yield return StartCoroutine (Start ())

the StartCoroutine (Start ());之前的2.Put yield return null;。您必须这样做,因为如果Start()协程中的所有逻辑(如while (Input.location.isEnabledByUser) )都无法运行,则不会有让步/等待,您将再次得到无限循环。

对你的loadTiles协程做同样的事情。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42741869

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档