通过使用异步任务和异步UnityWebRequest从Firebase获取随机照片的问题

时间:2019-07-02 09:14:56

标签: firebase unity3d asynchronous

我创建了对Firebase的调用以获取随机照片(由于我们具有照片类别,因此我首先尝试获取随机类别,然后从中获取随机照片)。之后,我想进行异步UnityWebRequest来获取照片并将其添加为纹理。代码进入了Task的内部,但是从未执行过对数据库的调用。我尝试使用代码单独获取图像,但效果很好。我也尝试使用委托和操作,但并没有太大帮助。我还是C#和Unity的新手,所以我的代码不是那么好。将感谢所有反馈。

我尝试使用代码单独获取图像,并且效果很好。我也尝试使用委托和操作,但并没有太大帮助。我还是C#和Unity的新手,所以我的代码不是那么好。将感谢所有反馈。

//获取随机照片

异步任务GetRandomPhoto(){         等待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];
                }
            });
        }
    });

}

///尝试将照片设置为纹理 公共异步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 :(得分:0)

我不太清楚您的两个代码块是如何结合在一起的,但是我要指出的是.ContinueWith不会在Unity的主线程中继续。我的怀疑是延续性是通过一种我没有看到的机制从GetTexture开始的。

据我所知,异步/等待应该始终停留在您的current execution context中,但也许Continuations正在使您的逻辑在Unity主线程之外执行。

由于您使用的是Firebase,因此将ContinueWith替换为extension method ContinueWithOnMainThread将非常容易测试。如果这样做没有帮助,您通常可以将异步/等待逻辑替换为继续执行任务,或者相当容易地将上面的示例转换为使用纯协程:

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

(您可以做得比我的示例更好,并且我尚未验证它是否可以运行。只是快速通过)

答案 1 :(得分:0)

衷心感谢所有尝试提供帮助的人!我终于找到解决问题的方法。我将异步任务更改为异步任务<“ Dictionary”>,并使其返回随机照片的所有数据(标签,链接,用户)。然后,我在其中编写了一个异步void: 字典photoData = await GetRandomPhoto(); 从那里开始非常简单。

相关问题