Проблема с получением случайной фотографии из Firebase с использованием асинхронных задач и асинхронной UnityWebRequest - PullRequest
0 голосов
/ 02 июля 2019

Я сделал звонок в Firebase, чтобы получить случайную фотографию (так как у нас есть категории фотографий, сначала я пытаюсь получить случайную категорию, а затем случайную фотографию из нее).После этого я хочу сделать асинхронный UnityWebRequest, чтобы получить фотографию и добавить ее в качестве текстуры.Код попадает внутрь Задачи, но вызов базы данных никогда не выполняется.Я попробовал код, чтобы получить изображение отдельно, и он работал просто отлично.Я также пытался использовать делегат и действие, но не сильно помог.Я все еще новичок в C # и Unity, так что мой код не так хорош.Буду признателен за все отзывы.

Я попробовал код, чтобы получить изображение отдельно, и он работал просто отлично.Я также пытался использовать делегат и действие, но не сильно помог.Я все еще новичок в C # и Unity, так что мой код не так хорош.Буду благодарен за все отзывы.

// Получение случайной фотографии

асинхронная задача GetRandomPhoto () {await photosDbReference.GetValueAsync (). ContinueWith (task => {

        List<string> snapshotList = new List<string>();
        List<string> snapsnotList2 = new List<string>();

        if(task.IsCompleted){

            int catNumber = Convert.ToInt32(task.Result.ChildrenCount);

            System.Random rnd = new System.Random();
            int randCat = rnd.Next(0, catNumber);

            foreach (DataSnapshot snapshot in task.Result.Children)
            {
                snapshotList.Add(snapshot.Key.ToString());
            }

            photosDbReference.Child(snapshotList[randCat]).GetValueAsync().ContinueWith(task2 =>{

                if(task2.IsCompleted){
                    int photosNumber = Convert.ToInt32(task2.Result.ChildrenCount);
                    System.Random rnd2 = new System.Random();
                    int randPhoto = rnd.Next(0, photosNumber);

                    foreach(DataSnapshot snap2 in task2.Result.Children){
                        snapsnotList2.Add(snap2.Child("Dblink").Value.ToString());
                    }

                    string photoLink = snapsnotList2[randPhoto];
                }
            });
        }
    });

}

// Попытка установить фотографию в качестве текстуры public async void PutTheTexture (string url) {

    Texture2D texture = await GetTexture(url);
    myImage.texture = texture;
}

public async Task<Texture2D> GetTexture(string url){
    Debug.Log("Started");
    UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);

    Debug.Log("Sending request: " + url);

    var asyncOp = www.SendWebRequest();

    Debug.Log("Request sent");

    while( asyncOp.isDone==false )
    {
        await Task.Delay( 1000/30 );
    }

    if( www.isNetworkError || www.isHttpError )
    {

        #if DEBUG
        Debug.Log( $"{ www.error }, URL:{ www.url }" );
        #endif
        return null;
    }
    else
    {
        return DownloadHandlerTexture.GetContent( www );
    }
}

Код попадает в Debug.Log ("Started"); внутри Задачи, но, по-видимому,запрос никогда не отправляется.

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

Большое спасибо всем, кто пытался помочь! Я наконец нашел способ решить проблему. Я изменил свою асинхронную задачу на асинхронную задачу <«Словарь»> и заставил ее возвращать подсказку со всеми данными случайной фотографии (метка, ссылка, пользователь). Затем я создал асинхронную пустоту, в которой я написал: Словарь photoData = await GetRandomPhoto (); Оттуда это было очень легко.

0 голосов
/ 03 июля 2019

Я не могу точно сказать, как ваши два блока кода сочетаются друг с другом, но я укажу, что .ContinueWith не будет продолжаться в основном потоке Unity. Я подозреваю, что продолжение запускает GetTexture через механизм, которого я не вижу.

Насколько я могу судить, async / await всегда должен оставаться в вашем текущем контексте выполнения , но, возможно, Continuations заставляют вашу логику выполняться вне основного потока Unity.

Поскольку вы используете Firebase, это было бы очень просто проверить, заменив ContinueWith на метод расширения ContinueWithOnMainThread. Если это не помогает, вы можете поменять логику async / await с продолжениями задач или довольно легко преобразовать приведенный выше пример для использования чисто сопрограмм:

//Getting the random photo
void GetRandomPhoto(){
    photosDbReference.GetValueAsync().ContinueWithOnMainThread(task =>
    {
        List<string> snapshotList = new List<string>();
        List<string> snapsnotList2 = new List<string>();

        if(task.IsCompleted){

            int catNumber = Convert.ToInt32(task.Result.ChildrenCount);

            System.Random rnd = new System.Random();
            int randCat = rnd.Next(0, catNumber);

            foreach (DataSnapshot snapshot in task.Result.Children)
            {
                snapshotList.Add(snapshot.Key.ToString());
            }

            photosDbReference.Child(snapshotList[randCat]).GetValueAsync().ContinueWithOnMainThread(task2 =>{

                if(task2.IsCompleted){
                    int photosNumber = Convert.ToInt32(task2.Result.ChildrenCount);
                    System.Random rnd2 = new System.Random();
                    int randPhoto = rnd.Next(0, photosNumber);

                    foreach(DataSnapshot snap2 in task2.Result.Children){
                        snapsnotList2.Add(snap2.Child("Dblink").Value.ToString());
                    }

                    string photoLink = snapsnotList2[randPhoto];
                }
            });
        }
    });
}

public delegate void GetTextureComplete(Texture2D texture);

private void Completion(Texture2D texture) {
    myImage.texture = texture;
}

//Trying to set the photo as a texture
public void PutTheTexture(string url){
    GetTexture(url, Completion);
}

public IEnumerator GetTexture(string url, GetTextureComplete completion){
    Debug.Log("Started");
    UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);

    Debug.Log("Sending request: " + url);

    var asyncOp = www.SendWebRequest();

    Debug.Log("Request sent");
    yield return asyncOp;

    if( www.isNetworkError || www.isHttpError )
    {

        #if DEBUG
        Debug.Log( $"{ www.error }, URL:{ www.url }" );
        #endif
        completion(null);
    }
    else
    {
        completion(DownloadHandlerTexture.GetContent(www));
    }
}

(вы можете сделать лучше, чем мой пример, и я не проверял, что он работает. Просто быстрый проход)

...