【问题标题】:UnityWebRequest never returns on script attached to a prefabUnityWebRequest 永远不会返回附加到预制件的脚本
【发布时间】:2019-11-15 11:01:49
【问题描述】:

我有一个 IEnumerator 函数,可以从服务器下载图像,在未附加到预制件的脚本上,它可以工作,但在附加到预制件的脚本上,它不起作用。

由于不起作用,我想说 www.SendWebRequest() 永远不会返回,我已经等了将近 10 分钟但它没有返回,图像大约有 200kb,所以问题不在于图像大小。

我已经检查了url是否正确,尝试更改图像,尝试重新编写函数但没有任何效果,这是我的函数:

public void Set(string NomeIcone, string NomeAnalise, string idzinho, string descricaozinha, string NomeCapa)
{
    Name.text = NomeAnalise;
    ID = idzinho;
    Descricao = descricaozinha;
    Capa = NomeCapa;
    StartCoroutine(LoadLogo(NomeIcone));
}

public IEnumerator LoadLogo(string nomeArquivo)
{
    string url = PathIcone + nomeArquivo;
    print(url);

    using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
    {
        yield return www.SendWebRequest();

        if (www.error == null)
        {
            Texture2D tex = new Texture2D(1, 1);
            tex = DownloadHandlerTexture.GetContent(www);
            Icon.texture = tex;
            RawImage Foto = Icon.GetComponentInChildren<RawImage>();
            Foto.SetNativeSize();
            float altura = 100 * Foto.rectTransform.rect.height / Foto.rectTransform.rect.width;
            Foto.rectTransform.sizeDelta = new Vector2(100, altura);
        }
    }
}

My prefab setup in the inspector

如您所见,我的“IconeSimbolo”是附加此脚本的预制件中的 RawImage

我希望我的“IconeSimbolo”纹理更改为服务器上的图像,但它永远不会改变。

我在另一个脚本上有相同的代码,在检查器上具有相同的设置,在另一个预制件上一切正常,但在这个它没有

【问题讨论】:

  • edit您的问题并解释您所说的“它不起作用”是什么意思。它会使编辑器崩溃吗?你的电脑会蓝屏吗?目前我们无法知道您所说的“它不起作用”是什么意思。另外,请包含您用于创建和启动 LoadCapa 协程的代码。
  • 我改变了一些东西,我希望现在更清楚了,谢谢!
  • 如果你在if (www.error == null) {...} 后面加上else { Debug.Log(www.error); },你看到那行打印了吗?从您告诉我们的情况来看,似乎无法确定它是否永远不会返回,或者是否只是一个错误。它可能使用了意外的PathIcone + nomeArquivo,而您遇到了 404 错误或其他问题。
  • 我尝试添加,但控制台上没有显示任何内容

标签: unity3d unitywebrequest


【解决方案1】:

这很简单:Update 方法不会在资产上执行,而只会在 在场景层次结构中处于活动状态并启用

GameObject/MonoBehaviour 上执行

&rightarrow;预制件不会收到 Update 调用。

在 Unity 中启动 CoroutinesUpdate 调用一起执行 (MoveNext)(或者更好地说 之后 - 参见 Order of Execution for Event Functions

&rightarrow;所以你的IEnumerator 开始并且实际上应该发送和返回请求......但是你永远不会在它上面调用MoveNext,所以它永远不会意识到请求已经完成。


您正在调用方法Set 的地方。因此,作为一种解决方法,您可以让一些GameObject/MonoBehaviour 为您执行IEnumerator,例如

public void Set(string NomeIcone, string NomeAnalise, string idzinho, string descricaozinha, string NomeCapa, MonoBehaviour responsibleBehaviour)
{
    Name.text = NomeAnalise;
    ID = idzinho;
    Descricao = descricaozinha;
    Capa = NomeCapa;

    // This now starts the coroutine instead on the passed 
    // responsibleBehaviour and uses that ones Update calls in order to
    // move on with the IEnumerator
    responsibleBehaviour.StartCoroutine(LoadLogo(NomeIcone));
}

在调用脚本中只需在参数末尾添加this(当然假设调用脚本是MonoBehaviour

prefab.Set(someNomeIcone, someNomeAnalise, someIdzinho, someDescricaozinha, someNomeCapa, this);

另外,既然你做了LoadLogopublic,你也可以直接使用另一个IEnumerator来执行它:

public IEnumerator LoadLogo(string NomeIcone, string NomeAnalise, string idzinho, string descricaozinha, string NomeCapa)
{
    Name.text = NomeAnalise;
    ID = idzinho;
    Descricao = descricaozinha;
    Capa = NomeCapa;

    string url = PathIcone + NomeIcone;
    print(url);

    using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
    {
        yield return www.SendWebRequest();

        if (www.error == null)
        {
            Texture2D tex = new Texture2D(1, 1);
            tex = DownloadHandlerTexture.GetContent(www);
            Icon.texture = tex;
            RawImage Foto = Icon.GetComponentInChildren<RawImage>();
            Foto.SetNativeSize();
            float altura = 100 * Foto.rectTransform.rect.height / Foto.rectTransform.rect.width;
            Foto.rectTransform.sizeDelta = new Vector2(100, altura);
        }
    }
}

然后在场景中的GameObject 上运行它,例如喜欢

public class SomeBehaviourInScene : MonoBehaviour
{
    // reference the Prefab here
    public YourPrefabScript prefab;

    // wherever you want to call this
    public void LoadPrefabLogo()
    {
        StartCoroutine(LoadPrefabLogoRoutine());
    }

    // If you want this to be called automatically
    // on app start this could also be a 
    //private IEnumerator Start()
    private IEnumerator LoadPrefabLogoRoutine()
    {
        // this also executes the LoadLogo and at 
        // the same time waits until it is finished
        yield return prefab.LoadLogo(/* Your parameters here */);

        Debug.Log("Finished");
    }
}

或者,如果这是关于 EditorScript,您可以注册到 EditorApplication.update,以便在您的 IEnumerator 上调用 MoveNext


一般旁注:为了方便和合作原因(例如,请参阅此处),您应该习惯为所有方法、变量以及 cmets 使用英文名称。

【讨论】:

  • 太棒了!有效!谢谢,我的变量名不是英文的,因为我在一家巴西公司工作,所以我必须用葡萄牙语调用变量
  • 那么您的公司应该习惯使用英语;)它是国际编程语言。我也是德国人,但无论如何我们都用英语编码和评论所有内容
猜你喜欢
  • 2013-10-25
  • 1970-01-01
  • 2019-11-15
  • 2011-07-25
  • 1970-01-01
  • 2012-10-02
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多