如何解决使用WebCamTexture时照片出现像素偏移线/画面撕裂问题?
解决WebCamTexture.GetPixels()画面撕裂问题(Android/iOS)
问题背景
调用WebCamTexture.GetPixels()获取相机画面时,偶尔出现画面撕裂(图像中存在一条像素偏移线),出现概率约5%,运动场景下更明显,静态拍摄也偶发。项目仅部署在Android和iOS平台,无法使用VR Photo Capture或Windows Photo Capture库。
已尝试暂停摄像头纹理并等待多个帧同步点,但问题未解决,相关代码如下:
// pause the webcam texture MyWebCamTexture.Pause(); // wait until we can see that it is no longer playing yield return new WaitUntil(CameraIsntPlaying()); // wait for the fixed update for good measure yield return new WaitForFixedUpdate(); // wait until end of frame yield return new WaitForEndOfFrame(); // get the pixels var pix = MyWebCamTexture.GetPixels(); // set the pixels to the texture textureRef.SetPixels(pix); // apply textureRef.Apply();
示例画面:
- 正常画面:

- 撕裂画面:

可行解决方案
1. 同步摄像头帧率与游戏帧率
设置WebCamTexture.requestedFPS匹配项目的目标帧率,减少纹理更新与游戏线程的异步冲突:
MyWebCamTexture.requestedFPS = Application.targetFrameRate;
2. 等待纹理完成完整帧更新后读取
依赖WebCamTexture.didUpdateThisFrame判断,确保读取的是完全更新后的一帧,而非半更新状态的纹理:
IEnumerator CaptureValidFrame() { // 等待纹理完成一次完整的帧更新 yield return new WaitUntil(() => MyWebCamTexture.didUpdateThisFrame); // 立即读取像素 var pix = MyWebCamTexture.GetPixels(); textureRef.SetPixels(pix); textureRef.Apply(); }
3. 引入像素缓冲层
维护一个独立的像素缓存数组,每次纹理更新时完整复制数据到缓存,从缓存读取使用,避免直接读取正在更新的纹理:
private Color[] _pixelCache; void Awake() { // 初始化缓存数组,大小匹配摄像头纹理 _pixelCache = new Color[MyWebCamTexture.width * MyWebCamTexture.height]; } IEnumerator CaptureFrameWithBuffer() { yield return new WaitUntil(() => MyWebCamTexture.didUpdateThisFrame); // 将纹理像素完整复制到缓存 MyWebCamTexture.GetPixels().CopyTo(_pixelCache, 0); // 使用缓存中的像素更新目标纹理 textureRef.SetPixels(_pixelCache); textureRef.Apply(); }
4. 调整读取时机至渲染同步点
将像素读取逻辑放在LateUpdate或OnRenderObject中,确保在当前帧渲染完成、纹理状态稳定后再读取:
void LateUpdate() { if (MyWebCamTexture.didUpdateThisFrame) { var pix = MyWebCamTexture.GetPixels(); textureRef.SetPixels(pix); textureRef.Apply(); } }
内容的提问来源于stack exchange,提问作者Andy Marshall
相关产品推荐
相关产品推荐

