【问题标题】:Can't return a string after value is true in coroutine在协程中值为真后无法返回字符串
【发布时间】:2019-12-20 07:14:27
【问题描述】:

我遇到了需要运行的协程的问题。它不断吐出一个错误,说它无法将 WaitUntil 转换为字符串,当我将 WaitUntil 添加到返回类型时,它又吐出另一个说它无法返回的错误。我已经尝试研究了几个小时,但无济于事。以下是代码片段:

     public string OpenSaveDialog(string Title, string OpenLocation, string[] AllowedExtentions)
     {
         OpenBtn.GetComponentInChildren<TMPro.TMP_Text>().text = "Save";
         TitleText.text = Title;
         AllowFileNameTyping = true;
         MultiSelect = false;

         LoadIntoExplorer(PathInput, AllowedExtentions);

         return StartCoroutine(WaitForFinish()); // Error here: Cannot implicitly convert type 'UnityEngine.Coroutine' to 'string'
     }

     IEnumerator<string> WaitForFinish()
     {
         yield return new WaitUntil(() => Done == true); // Error here: Cannot implicitly convert type 'UnityEngine.WaitUntil' to 'string'
         yield return FilePathsSelected[0];
     }

【问题讨论】:

  • 因为我需要它最终返回一个字符串,但我有一种感觉不是它的工作原理......在那种情况下,我如何让它返回一个字符串而不改变一切进入协程?
  • 是的,但是有没有办法从一个不是协程的协程中返回一个值,这样我就可以在我的函数中返回它?

标签: c# unity3d return coroutine


【解决方案1】:

您不能从协程返回值,您的选项是制作回调,类范围变量,指示协程的值,自定义类,具有 IsDone & value 或 result 属性,您也不能使用 ref, in 或 out 关键字也是因为迭代器不能使用它们:/ 所以这不起作用:

public IEnumerator WaitForFinnish(ref string value)
{
    yield return new WaitUntil(() => true);
    value = "value";
}

所以在你的情况下,我会做这样的事情:

string filePath = string.Empty;

public void OpenSaveDialog(string Title, string OpenLocation, string[] AllowedExtentions)
{
     OpenBtn.GetComponentInChildren<TMPro.TMP_Text>().text = "Save";
     TitleText.text = Title;
     AllowFileNameTyping = true;
     MultiSelect = false;

     LoadIntoExplorer(PathInput, AllowedExtentions);

     StartCoroutine(WaitForFinish());
 }

 IEnumerator WaitForFinish()
 {
     yield return new WaitUntil(() => Done); // Also don't do bool == true or false,
                                             // it will trigger most of the programmers :D
     filePath = FilePathsSelected[0];
 }

【讨论】:

    【解决方案2】:

    添加到Menyus' answer

    我宁愿选择回调方法

    public void OpenSaveDialog(string Title, string OpenLocation, string[] AllowedExtentions, Action<string> whenDone = null)
     {
         OpenBtn.GetComponentInChildren<TMPro.TMP_Text>().text = "Save";
         TitleText.text = Title;
         AllowFileNameTyping = true;
         MultiSelect = false;
    
         LoadIntoExplorer(PathInput, AllowedExtentions);
    
         StartCoroutine(WaitForFinish(whenDone));
     }
    
     IEnumerator WaitForFinish(Action<string> whenDone)
     {
         yield return new WaitUntil(() => Done);
    
         whenDone?.Invoke(FilePathsSelected[0]);
     }
    

    所以现在无论何时调用该方法,您都可以传入一个在完成后应该执行的操作,例如

    // as lambda expression
    OpenSaveDialog("Title", "Some/Path", new []{ ".example" }, path =>
        {
            Debug.Log($"The selected path is {path}");
        });
    
    //Or with a dedicated method 
    OpenSaveDialog("Title", "Some/Path", new []{ ".example" }, OnPathSelected);
    
    ...
    
    private void OnPathSelected (string path)
    {
        Debug.Log($"The selected path is {path}");
    }
    

    当然,我们看不到 LoadIntoExplorer 究竟做了什么。也许您甚至可以完全跳过协程,而是向该方法添加一个Action&lt;string&gt; 回调?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-11
      • 1970-01-01
      • 1970-01-01
      • 2020-12-22
      • 1970-01-01
      • 2021-10-22
      • 1970-01-01
      • 2021-09-03
      相关资源
      最近更新 更多