From f6d96eb877bd4c85644f4b60d6120ddc76aa3ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9C=E8=99=9E=E6=B8=A0=E6=88=90=E2=80=9D?= <“yuqucheng2006@qq.com”> Date: Thu, 23 Jul 2026 14:44:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(ios):=20=E6=96=B0=E5=A2=9EiOS=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E6=91=84=E5=83=8F=E5=A4=B4=E5=8E=9F=E7=94=9F=E5=AF=B9?= =?UTF-8?q?=E7=84=A6=E6=8F=92=E4=BB=B6=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增iOS原生插件CameraFocusHelper,实现连续自动对焦和曝光控制 2. 适配iOS平台的扫码对焦逻辑,替换原生Unity的自动对焦实现 3. 新增跨平台自动对焦维护协程,区分iOS和其他平台的对焦处理逻辑 4. 优化扫码对焦体验,限制对焦范围为近距并开启低光增强 --- Assets/Plugins/iOS/CameraFocusHelper.mm | 69 +++++++++++++++++++ .../UI/Pages/ConnectDevice/ScanQRcode.cs | 46 ++++++++++++- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 Assets/Plugins/iOS/CameraFocusHelper.mm diff --git a/Assets/Plugins/iOS/CameraFocusHelper.mm b/Assets/Plugins/iOS/CameraFocusHelper.mm new file mode 100644 index 0000000..4a41aaa --- /dev/null +++ b/Assets/Plugins/iOS/CameraFocusHelper.mm @@ -0,0 +1,69 @@ +#import +#import + +extern "C" { + + /// 启用连续自动对焦和自动曝光 + void _EnableContinuousAutoFocus() + { + dispatch_async(dispatch_get_main_queue(), ^{ + AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + if (!device) return; + + NSError *error = nil; + + // 锁定设备开始配置 + if ([device lockForConfiguration:&error]) { + + // 连续自动对焦模式(持续调整,适合扫描二维码) + if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) { + device.focusMode = AVCaptureFocusModeContinuousAutoFocus; + } + + // 连续自动曝光 + if ([device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) { + device.exposureMode = AVCaptureExposureModeContinuousAutoExposure; + } + + // 对焦范围限制为近距(适合二维码) + if ([device respondsToSelector:@selector(setAutoFocusRangeRestriction:)]) { + if ([device isAutoFocusRangeRestrictionSupported]) { + device.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear; + } + } + + // 启用低光增强(昏暗环境提高识别率) + if ([device respondsToSelector:@selector(setAutomaticallyEnablesLowLightBoostWhenAvailable:)]) { + device.automaticallyEnablesLowLightBoostWhenAvailable = YES; + } + + [device unlockForConfiguration]; + + NSLog(@"[CameraFocusHelper] 已启用连续自动对焦"); + } else { + NSLog(@"[CameraFocusHelper] 锁定设备失败: %@", error.localizedDescription); + } + }); + } + + /// 触发一次自动对焦(用于手动点按时调用) + void _TriggerAutoFocus() + { + dispatch_async(dispatch_get_main_queue(), ^{ + AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + if (!device) return; + + NSError *error = nil; + if ([device lockForConfiguration:&error]) { + if ([device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) { + device.focusMode = AVCaptureFocusModeAutoFocus; + } + if ([device isExposureModeSupported:AVCaptureExposureModeAutoExpose]) { + device.exposureMode = AVCaptureExposureModeAutoExpose; + } + [device unlockForConfiguration]; + } + }); + } + +} diff --git a/Assets/Scripts/UI/Pages/ConnectDevice/ScanQRcode.cs b/Assets/Scripts/UI/Pages/ConnectDevice/ScanQRcode.cs index eece869..ebdfdaa 100644 --- a/Assets/Scripts/UI/Pages/ConnectDevice/ScanQRcode.cs +++ b/Assets/Scripts/UI/Pages/ConnectDevice/ScanQRcode.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.InteropServices; using Kill.UI.Components; using UnityEngine; using UnityEngine.UI; @@ -41,6 +42,14 @@ namespace Kill.UI.Pages public bool enableAutoFocus = true; [Tooltip("对焦间隔(秒)")] public float focusInterval = 1f; + +#if UNITY_IOS && !UNITY_EDITOR + [DllImport("__Internal")] + private static extern void _EnableContinuousAutoFocus(); + + [DllImport("__Internal")] + private static extern void _TriggerAutoFocus(); +#endif // 摄像头相关 private WebCamTexture webCamTexture; private WebCamDevice currentDevice; @@ -162,7 +171,14 @@ namespace Kill.UI.Pages // 等待摄像头启动 yield return new WaitUntil(() => webCamTexture.width > 100); - webCamTexture.autoFocusPoint=new Vector2(0.5f,0.5f); + + // iOS: 调用原生插件强制开启连续自动对焦 +#if UNITY_IOS && !UNITY_EDITOR + if (enableAutoFocus) + { + _EnableContinuousAutoFocus(); + } +#endif // 调整预览画面比例 AdjustPreviewAspect(); @@ -170,6 +186,11 @@ namespace Kill.UI.Pages // 开始预览更新和扫描 StartCoroutine(PreviewUpdateCoroutine()); StartCoroutine(ScanCoroutine()); + // 启动自动对焦维护协程(仅非 iOS 平台使用 autoFocusPoint,iOS 走原生插件) + if (enableAutoFocus) + { + StartCoroutine(AutoFocusCoroutine()); + } } @@ -264,6 +285,29 @@ namespace Kill.UI.Pages previewTexture.Apply(); } + /// + /// 自动对焦维护协程 + /// iOS: 走原生插件(连续自动对焦已启用,只需定期触发即可) + /// 其他平台: 使用 WebCamTexture.autoFocusPoint 定期设置对焦点 + /// + private IEnumerator AutoFocusCoroutine() + { + while (isScanning) + { +#if UNITY_IOS && !UNITY_EDITOR + // iOS 通过原生插件触发一次自动对焦 + _TriggerAutoFocus(); +#else + // Android/其他: 定期重置对焦点到画面中心 + if (webCamTexture != null && webCamTexture.isPlaying) + { + webCamTexture.autoFocusPoint = new Vector2(0.5f, 0.5f); + } +#endif + yield return new WaitForSeconds(focusInterval); + } + } + [SerializeField] private float previewUpdateInterval = 0.03f; // 预览更新间隔(20fps) ///