Pro*_*mer 5 c# multithreading delegates closures unity-game-engine
我编写了一个Thread helper类,该类可用于执行Unity主线程中的一段代码。
这是功能蓝图:
public static void executeInUpdate(System.Action action)
Run Code Online (Sandbox Code Playgroud)
完整的脚本真的很长,会使这篇文章变得不必要。您可以在此处查看脚本助手类的其余部分。
然后,我可以从另一个Thread像这样使用unity的API :
UnityThread.executeInUpdate(() =>
{
transform.Rotate(new Vector3(0f, 90f, 0f));
});
Run Code Online (Sandbox Code Playgroud)
问题是,当我使用在该委托外部声明的变量时,它将分配内存。上面的代码每帧分配104个字节。那是因为transform该闭包内部使用了变量。
现在看来似乎什么都没有,但是我每秒要执行60次,并且我需要连接大约6台摄像机并在屏幕上显示图像。我不喜欢所产生的垃圾量。
以下是我如何从相机下载图像并将其上传到Unity的示例。我每秒获得约60帧。该receiveVideoFrame()函数在单独的线程上运行。它下载图像,将其发送到Unity主机,Thread然后Unity将图像字节上传到中Texture2D。在Texture2D随后与显示RawImage。当由于捕获闭包时发生分配UnityThread.executeInUpdate。
bool doneUploading = false;
byte[] videoBytes = new byte[25000];
public Texture2D videoDisplay;
void receiveVideoFrame()
{
while (true)
{
//Download Video Frame
downloadVideoFrameFromNetwork(videoBytes);
//Display Video Frame
UnityThread.executeInUpdate(() =>
{
//Upload the videobytes to Texture to display
videoDisplay.LoadImage(videoBytes);
doneUploading = true;
});
//Wait until video is done uploading to Texture/Displayed
while (!doneUploading)
{
Thread.Sleep(1);
}
//Done uploading Texture. Now set to false for the next run
doneUploading = false;
//Repeat again
}
}
Run Code Online (Sandbox Code Playgroud)
如何在不导致内存分配的情况下使用闭包?
如果不可能,还有另一种方法吗?
我只需要删除用于在主线程中执行代码的类,然后在主脚本中重新编写那些逻辑即可,但那会很麻烦而且很长。
经过几个小时的实验,我发现,如果将带有闭包的代码放入函数中,然后在or函数中将Action其缓存到变量中,则当您在 while 循环内调用它时,闭包内存分配将会消失。StartAwake
另外,我将doneUploading布尔变量设置为 a volatile,以便两者都Threads可以看到更改。我认为这里lock这个变量不需要关键字boolean。
private volatile bool doneUploading = false;
byte[] videoBytes = new byte[25000];
public Texture2D videoDisplay;
Action chachedUploader;
void Start()
{
chachedUploader = uploadToTexture;
}
void uploadToTexture()
{
UnityThread.executeInUpdate(() =>
{
//Upload the videobytes to Texture to display
videoDisplay.LoadImage(videoBytes);
doneUploading = true;
});
}
//running in another Thread
void receiveVideoFrame()
{
while (true)
{
//Download Video Frame
downloadVideoFrameFromNetwork(videoBytes);
//Display Video Frame (Called on main thread)
UnityThread.executeInUpdate(chachedUploader);
//Wait until video is done uploading to Texture/Displayed
while (!doneUploading)
{
Thread.Sleep(1);
}
//Done uploading Texture. Now set to false for the next run
doneUploading = false;
//Repeat again
}
}
Run Code Online (Sandbox Code Playgroud)
如果有人发现任何不好的地方,我愿意接受更多改进。虽然,我已经解决了我的问题。闭包不再分配内存。
| 归档时间: |
|
| 查看次数: |
348 次 |
| 最近记录: |