Xamarin.iOS原生侧截取Unity AR视图得到白屏如何解决
Xamarin.iOS 截取Unity AR视图白屏问题解决方案
问题原因
你使用的CALayer.RenderInContext方法只能捕获UIKit普通控件的CPU渲染内容,而Unity AR视图的相机画面、3D叠加元素都是通过Metal/OpenGL ES由GPU直接渲染到底部专用层,该方法无法读取GPU帧缓存内容,因此只会得到白屏。此外你的现有代码缺失了图像上下文初始化步骤,即使是普通UI截图也无法正常执行。
解决方案
方案1:Unity侧截图后回传原生(最稳定,推荐)
该方案兼容性最高,不会出现渲染API版本适配问题:
- Unity侧新增截图逻辑,捕获包含AR相机流和UI元素的完整帧后,将图片转为字节数组传给原生侧:
// Unity侧C#代码 public IEnumerator CaptureARView() { // 等待当前帧渲染完成 yield return new WaitForEndOfFrame(); // 捕获屏幕内容 Texture2D tex = ScreenCapture.CaptureScreenshotAsTexture(); // 转PNG字节数组 byte[] imgBytes = tex.EncodeToPNG(); Destroy(tex); // 通过你已有的Unity-原生交互通道把imgBytes传给Xamarin.iOS侧 }
- Xamarin.iOS侧接收到字节数组后直接转成UIImage存入相册即可:
public void ReceiveUnityScreenshot(byte[] imgBytes) { var img = UIImage.LoadFromData(NSData.FromArray(imgBytes)); img.SaveToPhotosAlbum((iRef, status) => { if (status != null) { new UIAlertView("Problem", status.ToString(), null, "OK", null).Show(); } else { new UIAlertView("Saved", "Saved", null, "OK", null).Show(); } }); }
方案2:原生侧直接抓取Unity GPU渲染层
如果你需要完全在原生侧完成操作,可直接抓取Unity RootView对应的Metal渲染层,注意需要适配Unity的渲染API:
UnityFramework _ufw; var unityView = _ufw.AppController().RootView; // 初始化图像上下文,参数分别为:尺寸、是否不透明、屏幕缩放比 UIGraphics.BeginImageContextWithOptions(unityView.Bounds.Size, false, UIScreen.MainScreen.Scale); var context = UIGraphics.GetCurrentContext(); // 等Unity当前帧渲染完成后再抓取 DispatchQueue.MainQueue.DispatchAsync(() => { // 直接渲染Unity视图的层,不要抓Window层 unityView.Layer.RenderInContext(context); var img = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); img.SaveToPhotosAlbum((iRef, status) => { if (status != null) { new UIAlertView("Problem", status.ToString(), null, "OK", null).Show(); } else { new UIAlertView("Saved", "Saved", null, "OK", null).Show(); } }); });
注意事项
- 如果使用ARFoundation,部分版本的相机流是单独渲染的纹理,需要在Unity侧将相机流和叠加元素合并到同一个RenderTexture后再导出,否则会出现只有UI没有相机画面的问题。
- 保存到相册前需要在Info.plist中添加
NSPhotoLibraryAddUsageDescription权限声明,否则会出现运行时崩溃。
内容的提问来源于stack exchange,提问作者Randi
相关产品推荐
相关产品推荐

