【问题标题】:Images appear in different order each time I enter in the scene每次我进入场景时,图像都会以不同的顺序出现
【发布时间】:2018-05-16 04:52:22
【问题描述】:

我有一个场景,我展示了从服务器下载的多个图像。它工作正常,但每次我进入场景时图像都会以不同的顺序显示,我希望始终以相同的顺序出现。有人可以帮帮我吗?

这是代码:

public GameObject contentRef;
public RawImage imgPrefab;

void Start()
{
DownloadtheFiles();
}

public void DownloadtheFiles()
{

List<string> photolist = ES2.LoadList<string>("myPhotos.txt");

for (int i = 0; i < photolist.Count; i++)
{
    //Don't capture i variable
    int index = i;

    new GetUploadedRequest()

        .SetUploadId(photolist[index])
        .Send((response) =>
        {
            StartCoroutine(DownloadImages(response.Url, index));
        });
}
}


public IEnumerator DownloadImages(string downloadUrl, int index)
{
var www = new WWW(downloadUrl);
yield return www;

//Instantiate the image prefab GameObject and make it a child of the contentRef
RawImage newImg = Instantiate(imgPrefab, contentRef.transform);
//Change the name
newImg.name = "Image-" + index;

//Get the downloaded image
Texture2D tex = new Texture2D(4, 4);
www.LoadImageIntoTexture(tex);

//Apply the downloaded image
newImg.texture = tex;
}

这些是我两次进入场景时不同图像位置的截图:

【问题讨论】:

  • 协程是 Unity 特定的多任务处理方式。一旦你开始了多个任务,它们完成的顺序就不再是确定的了。您也许可以制作一个单独的 CoRoutine,以给定的顺序完成所有下载和显示。但是这样做可能不利于网络性能(许多小文件可以从并行下载大量文件中受益)。

标签: c# unity3d


【解决方案1】:

WWW API 是线程化的,因此当您使用它时它不会阻塞您的 Unity 游戏。该线程由协程管理,使用yield return www; 等待请求直到完成。您正在使用 for 循环调用下载图像的 DownloadImages 函数。问题是WWW 调用不会阻止请求,并且会根据数据/图像的大小以及服务器响应所需的时间来完成。

如果要按顺序下载图像,则必须将 DownloadtheFiles 函数设为协程函数,而不是 void 函数。在此之后,当您调用 StartCoroutine(DownloadImages(response.Url, index)); 时,请等待它返回或完成,然后再继续执行 for 循环。通常,为此使用简单的yield return,但由于您从 lambda 调用StartCoroutine,因此此处使用Action 的回调更合适。您可以使用 boolean 变量和 Action 来告诉 for 循环当前的 DownloadImages 已完成,以便它可以继续。

public GameObject contentRef;
public RawImage imgPrefab;

void Start()
{
    StartCoroutine(DownloadtheFiles());
}

public IEnumerator DownloadtheFiles()
{
    yield return null;

    List<string> photolist = ES2.LoadList<string>("myPhotos.txt");

    for (int i = 0; i < photolist.Count; i++)
    {
        //Don't capture i variable
        int index = i;

        bool reqDone = false;

        new GetUploadedRequest()

            .SetUploadId(photolist[index])
            .Send((response) =>
            {
                StartCoroutine(DownloadImages(response.Url, index,
                    (status) => { reqDone = status; }));


                //return null;
            });

        //Wait in the for loop until the current request is done
        while (!reqDone)
            yield return null;
    }
}

public IEnumerator DownloadImages(string downloadUrl, int index, Action<bool> done)
{
    var www = new WWW(downloadUrl);
    yield return www;

    //Instantiate the image prefab GameObject and make it a child of the contentRef
    RawImage newImg = Instantiate(imgPrefab, contentRef.transform);
    //Change the name
    newImg.name = "Image-" + index;

    //Get the downloaded image
    Texture2D tex = new Texture2D(4, 4);
    www.LoadImageIntoTexture(tex);

    //Apply the downloaded image
    newImg.texture = tex;

    //Done
    if (done != null)
        done(true);
}

另一种解决方案是下载纹理并将它们存储在列表中但不要实例化它们。当 for 循环完成运行时,按名称对 List 进行排序,然后从列表中实例化 RawImage。

【讨论】:

  • 太棒了!!!它现在工作正常。图像以正确的顺序出现,但有点慢。图像是否可能显示得更快?
  • 你可以通过实现我在代码之后提到的第二种方法来让它看起来更快。如果我解决了您的“出现顺序问题”,请不要忘记接受答案。
  • 如果您无法实施我提到的第二种解决方案,请创建一个关于它的新帖子,但显示您尝试实施的尝试,我会看看它。
  • 非常感谢!我要开一篇关于它的新帖子
  • 我已经用我的工具创建了这篇文章,但不起作用。这是链接:stackoverflow.com/questions/50389586/…
猜你喜欢
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多