Hololens 2摄像头捕获内存泄漏问题求助
HoloLens 2摄像头捕获内存泄漏问题修复方案
WebCamTexture 内存泄漏修复
原代码核心问题是频繁启停WebCamTexture时未正确释放底层资源,且缺少销毁阶段的资源清理逻辑。修复后的代码如下:
private WebCamTexture webCamTexture; private RawImage rawImage; private void OnDestroy() { // 销毁时彻底释放WebCamTexture资源 if (webCamTexture != null) { webCamTexture.Stop(); Destroy(webCamTexture); webCamTexture = null; } } public IEnumerator Play() { yield return Application.RequestUserAuthorization(UserAuthorization.WebCam); if (!Application.HasUserAuthorization(UserAuthorization.WebCam)) yield break; WebCamDevice[] devices = WebCamTexture.devices; if (devices.Length == 0) yield break; // 仅初始化一次WebCamTexture,避免重复分配内存 webCamTexture = new WebCamTexture(devices[0].name, 1920, 1080, 30); rawImage.texture = webCamTexture; while (true) { if (!webCamTexture.isPlaying) { webCamTexture.Play(); } // 等待一帧确保画面更新完成,替代固定1秒等待 yield return new WaitForEndOfFrame(); webCamTexture.Stop(); // 强制触发GC,清理底层未自动回收的资源 System.GC.Collect(); yield return new WaitForSeconds(60); } }
关键修复点:
- 在
OnDestroy中手动销毁WebCamTexture并置空,防止场景销毁后残留内存引用 - 只创建一次WebCamTexture对象,避免重复分配内存
- 用
WaitForEndOfFrame优化等待逻辑,减少不必要的资源占用 - 每次循环后触发GC,清理Hololens底层未自动回收的资源
PhotoCapture 内存泄漏修复
原代码核心问题是每次捕获都新建Texture2D但未销毁旧纹理,且遗漏帧数据读取逻辑,导致空纹理占用内存。修复后的代码如下:
private PhotoCapture photoCaptureObject; private RawImage rawImage; private Texture2D currentTexture; // 保存当前纹理引用,方便销毁旧资源 private void OnDestroy() { // 销毁时统一清理所有资源 if (photoCaptureObject != null) { photoCaptureObject.Dispose(); photoCaptureObject = null; } if (currentTexture != null) { Destroy(currentTexture); currentTexture = null; } } public IEnumerator Play() { while (true) { PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated); // 等待当前捕获流程完全结束,替代固定10秒等待 yield return new WaitUntil(() => photoCaptureObject == null); // 强制GC回收残留资源 System.GC.Collect(); yield return new WaitForSeconds(60); } } void OnPhotoCaptureCreated(PhotoCapture captureObject) { photoCaptureObject = captureObject; CameraParameters c = new CameraParameters(); c.hologramOpacity = 0.0f; c.cameraResolutionWidth = 1920; c.cameraResolutionHeight = 1080; c.pixelFormat = CapturePixelFormat.BGRA32; captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted); } private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result) { if (result.success) { photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory); } else { Debug.LogError("无法启动拍照模式!"); photoCaptureObject.Dispose(); photoCaptureObject = null; } } void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame) { if (result.success) { // 销毁旧纹理,释放内存 if (currentTexture != null) { Destroy(currentTexture); } // 创建对应分辨率的纹理 currentTexture = new Texture2D(1920, 1080, TextureFormat.BGRA32, false); // 读取捕获帧数据到纹理(原代码遗漏此步骤,导致空纹理占用内存) photoCaptureFrame.UploadImageDataToTexture(currentTexture); rawImage.texture = currentTexture; } photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode); } void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result) { photoCaptureObject.Dispose(); photoCaptureObject = null; }
关键修复点:
- 新增
currentTexture变量保存当前纹理引用,每次捕获前销毁旧纹理释放内存 - 补充
UploadImageDataToTexture方法读取帧数据,避免创建空纹理浪费内存 - 用
WaitUntil替代固定等待,确保捕获流程完全结束后再进入下一轮 - 在
OnDestroy中统一清理所有资源,防止内存残留
额外优化建议
- 降低捕获分辨率:如果业务允许,将1920x1080改为1280x720,可大幅减少单帧内存占用
- 关闭后台冗余服务:在HoloLens设置中关闭未使用的应用和服务,释放系统内存
- 用Unity Profiler排查:将HoloLens连接到Unity Profiler,查看Memory面板的纹理资源占用,精准定位泄漏点
- 升级Unity版本:尝试升级到2022.3.x的最新补丁版本,部分内存泄漏问题可能已被官方修复
内容的提问来源于stack exchange,提问作者user24910611
相关产品推荐
相关产品推荐

