【问题标题】:Correct way to use multiple coroutines使用多个协程的正确方法
【发布时间】:2018-04-17 09:55:51
【问题描述】:

我只是觉得有更好的方法。我有一个需要调整大小然后压缩的纹理。这两个函数都需要一些处理时间,所以我需要将每个函数放入协程中。我得到它的方式是我先调整大小然后压缩,但事情似乎很快就会变得混乱。构建多个有序协程以依次触发并将处理后的变量(在本例中为 Texture2D)从一个传递到下一个的推荐方法是什么?

[Client]
    public void PrepareServerData(Texture2D texToSend, string typeToSend)
    {
        StartCoroutine(DoGetTexToBytes(texToSend));

        playerObj.texWidth = texToSend.width;
        playerObj.texHeight = texToSend.height;
        playerObj.texFormat = texToSend.format;
        playerObj.tranX = tran.x;
        playerObj.tranY = tran.y;
        playerObj.tranZ = tran.z;
        playerObj.type = typeToSend;
        Player_ID id = GetComponent<Player_ID>();
        playerObj.id = id.MakeUniqueIdentity();
        playerObj.strength = strengthToSend;
        playerObj.hitpoints = hitPointsToSend;

        Network_Serializer serialize = GetComponent<Network_Serializer>();

        // Send Data from Client to Server as many small sequenced packets
        byte[] bytes = serialize.ObjectToByteArray(playerObj);

        StartCoroutine(Network_Transmitter.instance.DoSendBytes(0, bytes));
    }

    IEnumerator DoGetTexToBytes(Texture2D tex)
    {
        DoResizeTex(tex);

        byte[] texBytes = tex.GetRawTextureData();                      // convert texture to raw bytes
        byte[] compressedTexBytes = lzip.compressBuffer(texBytes, 9);   // compress texture byte array
        playerObj.texBytes = compressedTexBytes;                        // set compressed bytes to player object

        yield return new WaitForEndOfFrame();

        GameObject infoDisplayText = GameObject.Find("InfoDisplay");
        infoDisplayText.GetComponent<Text>().text += "Bytes to send : " + playerObj.texBytes.Length + "\n";
    }

    IEnumerator DoResizeTex(Texture2D tex)
    {
        tex.ResizePro(1280, 1024);
        tex.Apply();

        yield return new WaitForEndOfFrame();
    }

【问题讨论】:

    标签: c# unity3d coroutine


    【解决方案1】:

    为你的协程添加一个回调进程。

    private IEnumerator MyCoroutine(Action callback){
        yield return null;
        if (callback !=null){callback();}
    }
    

    用法:

    void Start(){
        StartCoroutine(MyCoroutine(()=>
        { 
            StartCoroutine(OtherCoroutine());
        }
    }
    

    如果需要,您还可以使用 Action 从协程返回值。

     private IEnumerator MyCoroutine(Action<Texture2D> callback){
             yield return null; 
             Texture2D tex = GetTexture();
             if (callback !=null){callback(tex);}
      }
    
     void Start(){
            StartCoroutine(MyCoroutine((texParam)=>
           { 
                StartCoroutine(OtherCoroutine(texParam));
            }
      }
    
    IEnumerator OtherCoroutine(Texture2D texture){
           yield return null;
           texture.DoSomething();
     }
    

    【讨论】:

      【解决方案2】:

      如果您需要在DoGetTexToBytes 开始之前完成DoResizeTex,那么您需要使用yield 从DoGetTexToBytes 内部调用它:

      IEnumerator DoGetTexToBytes(Texture2D tex)
          {
              yield return StartCoroutine(DoResizeTex(tex));
      
              // Stuff done by DoGetTexToBytes after DoResizeTex has finished
          }
      
      IEnumerator DoResizeTex(Texture2D tex)
          {
              tex.ResizePro(1280, 1024);
              tex.Apply();
      
              yield return new WaitForEndOfFrame();
          }
      

      编辑:尚不清楚调整后的纹理是否必须由 DoGetTexToBytes 使用,但我想是的。如果是这种情况,您需要通过引用传递纹理,使用数组(修改上面的代码以添加纹理的引用传递)。基本上,您将使用只有一个元素的Texture2D[],而texToSend[0] 是您的旧texToSend。

      【讨论】:

      • 感谢您提供的信息,但我收到一个错误:迭代器在IEnumerator DoResizeTex(ref Texture2D tex) 行不能有 ref 或 out 参数。还有其他方法吗?
      • 这就是为什么我不应该在一整天的编码后在晚上回答的原因,我提出了错误的解决方案。 :) 实际上,您不能使用ref 或out 将参数传递给迭代器,为此,您需要使用数组来欺骗它(默认情况下按值传递引用,这意味着对元素的任何更改数组将反映在迭代器范围之外)。我会用适当的代码修改我的答案。
      • 但是只有一个纹理可以返回。为什么是数组?
      • @Everts 出于某种原因,我认为Texture2D 是struct 而不是class。确实没有理由将变量装箱,因为它已经是引用类型,我的错。将(再次)更正代码。只是想指出,如果参数是 struct 和 Vector3 一样,则需要将其装箱到数组中,以便调用者看到更改。
      猜你喜欢
      • 2019-06-07
      • 1970-01-01
      • 1970-01-01
      • 2018-09-16
      • 2020-07-28
      • 1970-01-01
      • 2017-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多