我写了一个Thread帮助器类,可以用来在Unity的主线程中执行一段代码.
这是蓝图的功能:
public static void executeInUpdate(System.Action action)
完整的脚本非常长,会使这个帖子不必要地长.您可以看到脚本助手类here的其余部分.
然后我可以使用另一个Thread中的unity的API,如下所示:
UnityThread.executeInUpdate(() =>
{
transform.Rotate(new Vector3(0f, 90f, 0f));
});
问题是当我使用在该委托之外声明的变量时,它会分配内存.上面的代码每帧分配104个字节.那是因为在闭包内部使用的变换变量.
现在看起来似乎什么都没有,但我这样做每秒60次,我有大约6个相机,我需要连接到屏幕上显示图像.我不喜欢生成的垃圾量.
下面是我如何从相机下载图像并将其上传到Unity的示例.我每秒约60帧. receiveVideoFrame()函数在单独的Thread上运行.它下载图像,将其发送到Unity的主线程,Unity将图像字节上传到Texture2D
.然后,纹理2D显示为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
}
}
如何在不引起内存分配的情况下使用闭包?
如果那是不可能的,还有另一种方法吗?
我可以删除我用来在主线程中执行代码的类,并在主脚本中重写这些逻辑,但这将是混乱和冗长的.
最佳答案 经过几个小时的实验,我发现如果你把带闭包的代码放在一个函数中,然后在Start或Awake函数中将它缓存到一个Action变量,当你在while循环中调用它时,闭包内存分配就会消失.
另外,我将doneUploading布尔变量设置为volatile,以便两个线程都可以看到更改.我不认为这个布尔变量需要lock关键字.
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
}
}
如果有人发现任何坏事,我愿意接受更多改进.虽然,我已经解决了我的问题.闭包不再分配内存.