使用多个协程的正确方法
Correct way to use multiple coroutines
我只是觉得有更好的方法。我有一个纹理需要调整大小,然后进行压缩。这两个函数都需要一些处理时间,所以我需要将每个函数都放在一个协程中。我得到它的方式是先调整大小然后压缩,但事情似乎很快就会变得混乱。构建多个有序协程以一个接一个触发并将处理后的变量(在本例中为 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();
}
如果您需要 DoResizeTex
在 DoGetTexToBytes
开始之前完成,那么您需要使用 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
.
为您的协程添加一个回调过程。
private IEnumerator MyCoroutine(Action callback){
yield return null;
if (callback !=null){callback();}
}
用法:
void Start(){
StartCoroutine(MyCoroutine(()=>
{
StartCoroutine(OtherCoroutine());
}
}
如果需要,您还可以 return 来自协程的值与 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();
}
我只是觉得有更好的方法。我有一个纹理需要调整大小,然后进行压缩。这两个函数都需要一些处理时间,所以我需要将每个函数都放在一个协程中。我得到它的方式是先调整大小然后压缩,但事情似乎很快就会变得混乱。构建多个有序协程以一个接一个触发并将处理后的变量(在本例中为 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();
}
如果您需要 DoResizeTex
在 DoGetTexToBytes
开始之前完成,那么您需要使用 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
.
为您的协程添加一个回调过程。
private IEnumerator MyCoroutine(Action callback){
yield return null;
if (callback !=null){callback();}
}
用法:
void Start(){
StartCoroutine(MyCoroutine(()=>
{
StartCoroutine(OtherCoroutine());
}
}
如果需要,您还可以 return 来自协程的值与 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();
}