From 807f940cfb0dbb21bdcab280bd88793257e131cb 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 15:48:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(iOS):=20=E6=96=B0=E5=A2=9E=E5=8E=9F?= =?UTF-8?q?=E7=94=9F=E7=9B=B8=E6=9C=BA=E5=AF=B9=E7=84=A6=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=B9=B6=E9=80=82=E9=85=8D=E6=89=AB=E7=A0=81=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增iOS平台原生相机对焦辅助插件,支持开启连续自动对焦和点击单点对焦 2. 适配扫码页面,iOS平台使用原生插件实现对焦功能,修复Unity自带autoFocusPoint无效问题 3. 添加点击屏幕触发单点对焦,1.5秒后自动恢复连续对焦 4. 新增定时维护对焦状态的协程,防止系统重置对焦模式 --- Assets/Plugins/iOS/CameraFocusHelper.mm | 71 +++++++++++++++++++ Assets/Plugins/iOS/CameraFocusHelper.mm.meta | 33 +++++++++ .../UI/Pages/ConnectDevice/ScanQRcode.cs | 58 +++++++++++++-- 3 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 Assets/Plugins/iOS/CameraFocusHelper.mm create mode 100644 Assets/Plugins/iOS/CameraFocusHelper.mm.meta diff --git a/Assets/Plugins/iOS/CameraFocusHelper.mm b/Assets/Plugins/iOS/CameraFocusHelper.mm new file mode 100644 index 0000000..54b9a2a --- /dev/null +++ b/Assets/Plugins/iOS/CameraFocusHelper.mm @@ -0,0 +1,71 @@ +#import +#import + +/// 获取当前正在使用的后置摄像头设备 +static AVCaptureDevice *GetActiveRearCamera(void) +{ + // 遍历所有正在运行的 AVCaptureSession,找到后置摄像头的输入 + if (@available(iOS 10.0, *)) { + AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession + discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] + mediaType:AVMediaTypeVideo + position:AVCaptureDevicePositionBack]; + for (AVCaptureDevice *d in session.devices) { + if (d.deviceType == AVCaptureDeviceTypeBuiltInWideAngleCamera) { + return d; + } + } + } + return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; +} + +extern "C" { + + /// 开启连续自动对焦 + void _EnableContinuousAutoFocus(void) + { + AVCaptureDevice *device = GetActiveRearCamera(); + if (!device) return; + + NSError *error = nil; + if ([device lockForConfiguration:&error]) { + if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) { + device.focusMode = AVCaptureFocusModeContinuousAutoFocus; + NSLog(@"[CameraFocusHelper] 已开启连续自动对焦"); + } + if ([device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) { + device.exposureMode = AVCaptureExposureModeContinuousAutoExposure; + } + [device unlockForConfiguration]; + } else { + NSLog(@"[CameraFocusHelper] 配置失败: %@", error.localizedDescription); + } + } + + /// 触发单次自动对焦(点击对焦用) + void _TriggerAutoFocus(float normalizedX, float normalizedY) + { + AVCaptureDevice *device = GetActiveRearCamera(); + if (!device) return; + + NSError *error = nil; + if ([device lockForConfiguration:&error]) { + if ([device isFocusPointOfInterestSupported]) { + device.focusPointOfInterest = CGPointMake(normalizedX, normalizedY); + device.focusMode = AVCaptureFocusModeAutoFocus; + } + if ([device isExposurePointOfInterestSupported]) { + device.exposurePointOfInterest = CGPointMake(normalizedX, normalizedY); + device.exposureMode = AVCaptureExposureModeAutoExpose; + } + [device unlockForConfiguration]; + + // 1.5秒后恢复连续对焦 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + _EnableContinuousAutoFocus(); + }); + } + } + +} diff --git a/Assets/Plugins/iOS/CameraFocusHelper.mm.meta b/Assets/Plugins/iOS/CameraFocusHelper.mm.meta new file mode 100644 index 0000000..94922d0 --- /dev/null +++ b/Assets/Plugins/iOS/CameraFocusHelper.mm.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bfac996797a54a14fa60abaaaf887145 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UI/Pages/ConnectDevice/ScanQRcode.cs b/Assets/Scripts/UI/Pages/ConnectDevice/ScanQRcode.cs index eece869..a98cb43 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,15 @@ 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(float normalizedX, float normalizedY); +#endif + // 摄像头相关 private WebCamTexture webCamTexture; private WebCamDevice currentDevice; @@ -60,6 +70,22 @@ namespace Kill.UI.Pages StopScan(); } + void Update() + { +#if UNITY_IOS && !UNITY_EDITOR + if (isScanning && Input.touchCount > 0) + { + Touch touch = Input.GetTouch(0); + if (touch.phase == TouchPhase.Began) + { + float normX = touch.position.x / Screen.width; + float normY = touch.position.y / Screen.height; + _TriggerAutoFocus(normX, normY); + } + } +#endif + } + /// /// 开始扫描 /// @@ -151,18 +177,22 @@ namespace Kill.UI.Pages } } RectTransform cameraPreviewRect=cameraPreview.GetComponent(); - // 使用较低的扫描分辨率以提高性能 - int targetWidth = 2160; - - // 创建摄像头纹理 - webCamTexture = new WebCamTexture(deviceName, targetWidth, 30); + // 使用 1080p 分辨率 + webCamTexture = new WebCamTexture(deviceName, 1920, 1080, 30); // 开始播放 webCamTexture.Play(); // 等待摄像头启动 yield return new WaitUntil(() => webCamTexture.width > 100); - webCamTexture.autoFocusPoint=new Vector2(0.5f,0.5f); + +#if UNITY_IOS && !UNITY_EDITOR + // iOS: 通过原生插件开启连续自动对焦(autoFocusPoint 在 iOS 无效) + _EnableContinuousAutoFocus(); + // 定期维护对焦状态,防止被系统重置 + StartCoroutine(IOsFocusMaintainCoroutine()); +#endif + webCamTexture.autoFocusPoint = new Vector2(0.5f, 0.5f); // 调整预览画面比例 AdjustPreviewAspect(); @@ -215,7 +245,21 @@ namespace Kill.UI.Pages Debug.Log($"[ScanQRcode] 预览调整 - 相机: {cameraWidth}x{cameraHeight}, 预览: {previewWidth}x{previewHeight}"); } - + +#if UNITY_IOS && !UNITY_EDITOR + /// + /// iOS 对焦维护协程 — 定期重新设置连续自动对焦,防止被系统重置 + /// + private IEnumerator IOsFocusMaintainCoroutine() + { + while (isScanning) + { + yield return new WaitForSeconds(3f); + _EnableContinuousAutoFocus(); + } + } +#endif + private Texture2D previewTexture; ///