Unity调用EmguCV转换Texture2D至Image时崩溃问题求助
Unity崩溃排查:Texture2D转EmguCV Image时无报错直接崩溃
我之前也碰到过类似的非托管内存冲突导致的Unity崩溃,完全懂你这种看不到报错只能瞎猜的痛苦!结合你的代码和描述,这个问题大概率是EmguCV非托管内存和Unity托管内存交互时的访问违规,而且这种错误会绕过.NET的异常捕获,直接让进程挂掉。
先把你的问题场景和代码再明确下:
调用SetTextureDefault函数将Unity的Texture2D转为EmguCV的Image<Bgra, byte>时,Unity编辑器和独立包都会直接弹出崩溃窗口,没有任何报错日志;移除这个函数后程序运行正常。使用的是个人版Unity + 桌面版EmguCV,相关代码如下:
void SetTextureDefault() { try { Texture2D currentTexture = new Texture2D(CameraTexture.width, CameraTexture.height); currentTexture.SetPixels(CameraTexture.GetPixels()); currentTexture.Apply(); // Assuming leftBackground and rightBackground of Image<Bgra, byte> exist if (leftBackground == null || rightBackground == null) { using (var ms = new MemoryStream(currentTexture.EncodeToPNG())) { leftBackground = new Image<Bgra, byte>(new Bitmap(ms)); } } else { rightBackground.Bytes = leftBackground.Bytes = currentTexture.EncodeToPNG(); } } catch (Exception err) { Debug.Log(err.StackTrace); } }
问题根源拆解
你的代码里有几个明显的高危操作,直接触发了内存访问违规:
- 直接赋值
Bytes属性:EmguCV的Image.Bytes背后是指向非托管内存的指针,你直接把Unity生成的托管byte数组赋值给它,会导致非托管内存和托管内存的生命周期脱节——当.NET GC回收这个byte数组时,EmguCV还在尝试访问这块已经被释放的内存,直接触发崩溃。 - Bitmap资源未正确释放:通过
new Bitmap(ms)创建Bitmap再转EmguCVImage时,Bitmap的非托管内存没有被正确释放,积累下来会导致内存冲突。 - Texture2D未销毁:Unity的
Texture2D是引擎管理的资源,直接创建后不销毁,会导致内存泄漏,间接引发崩溃。
修复后的完整代码
针对这些问题,我调整了代码,确保内存管理正确:
void SetTextureDefault() { try { // 使用using自动销毁Texture2D,避免Unity内存泄漏 using (Texture2D currentTexture = new Texture2D(CameraTexture.width, CameraTexture.height, TextureFormat.RGBA32, false)) { currentTexture.SetPixels(CameraTexture.GetPixels()); currentTexture.Apply(); byte[] pngBytes = currentTexture.EncodeToPNG(); if (leftBackground == null || rightBackground == null) { // 使用嵌套using确保Bitmap和MemoryStream都被正确释放 using (var ms = new MemoryStream(pngBytes)) using (var bmp = new Bitmap(ms)) { leftBackground = Image<Bgra, byte>.FromBitmap(bmp); // 初始化rightBackground为独立的克隆对象,避免共享内存 rightBackground = leftBackground.Clone(); } } else { // 不要直接赋值Bytes,用FromArray/FromBitmap创建新的Image,让EmguCV管理内存 using (var ms = new MemoryStream(pngBytes)) using (var bmp = new Bitmap(ms)) { // 先释放旧的Image资源,避免内存泄漏 leftBackground.Dispose(); rightBackground.Dispose(); leftBackground = Image<Bgra, byte>.FromBitmap(bmp); rightBackground = leftBackground.Clone(); } } } } catch (Exception err) { // 用Debug.LogError更容易在控制台看到错误 Debug.LogError($"SetTextureDefault出错: {err.Message}\n{err.StackTrace}"); } }
额外调试建议
- 启用Unity Profiler:打开
Window > Analysis > Profiler,切换到Memory面板,监测Texture和托管内存的变化,看是否有异常增长。 - 关闭EmguCV的OpenCL加速:在初始化EmguCV时添加
CvInvoke.UseOpenCL = false;,有时候OpenCL的内存管理会和Unity冲突。 - 检查EmguCV日志:可以在代码开头添加
CvInvoke.RedirectError(CvErrorHandler);自定义错误回调,捕获底层OpenCV的错误信息。
内容的提问来源于stack exchange,提问作者Frengky Sinaga
相关产品推荐
相关产品推荐

