feat(ios): 新增iOS平台摄像头原生对焦插件适配
1. 新增iOS原生插件CameraFocusHelper,实现连续自动对焦和曝光控制 2. 适配iOS平台的扫码对焦逻辑,替换原生Unity的自动对焦实现 3. 新增跨平台自动对焦维护协程,区分iOS和其他平台的对焦处理逻辑 4. 优化扫码对焦体验,限制对焦范围为近距并开启低光增强
This commit is contained in:
parent
8972a69e86
commit
f6d96eb877
69
Assets/Plugins/iOS/CameraFocusHelper.mm
Normal file
69
Assets/Plugins/iOS/CameraFocusHelper.mm
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using Kill.UI.Components;
|
using Kill.UI.Components;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
@ -41,6 +42,14 @@ namespace Kill.UI.Pages
|
|||||||
public bool enableAutoFocus = true;
|
public bool enableAutoFocus = true;
|
||||||
[Tooltip("对焦间隔(秒)")]
|
[Tooltip("对焦间隔(秒)")]
|
||||||
public float focusInterval = 1f;
|
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 WebCamTexture webCamTexture;
|
||||||
private WebCamDevice currentDevice;
|
private WebCamDevice currentDevice;
|
||||||
@ -162,7 +171,14 @@ namespace Kill.UI.Pages
|
|||||||
|
|
||||||
// 等待摄像头启动
|
// 等待摄像头启动
|
||||||
yield return new WaitUntil(() => webCamTexture.width > 100);
|
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();
|
AdjustPreviewAspect();
|
||||||
|
|
||||||
@ -170,6 +186,11 @@ namespace Kill.UI.Pages
|
|||||||
// 开始预览更新和扫描
|
// 开始预览更新和扫描
|
||||||
StartCoroutine(PreviewUpdateCoroutine());
|
StartCoroutine(PreviewUpdateCoroutine());
|
||||||
StartCoroutine(ScanCoroutine());
|
StartCoroutine(ScanCoroutine());
|
||||||
|
// 启动自动对焦维护协程(仅非 iOS 平台使用 autoFocusPoint,iOS 走原生插件)
|
||||||
|
if (enableAutoFocus)
|
||||||
|
{
|
||||||
|
StartCoroutine(AutoFocusCoroutine());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -264,6 +285,29 @@ namespace Kill.UI.Pages
|
|||||||
previewTexture.Apply();
|
previewTexture.Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自动对焦维护协程
|
||||||
|
/// iOS: 走原生插件(连续自动对焦已启用,只需定期触发即可)
|
||||||
|
/// 其他平台: 使用 WebCamTexture.autoFocusPoint 定期设置对焦点
|
||||||
|
/// </summary>
|
||||||
|
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)
|
[SerializeField] private float previewUpdateInterval = 0.03f; // 预览更新间隔(20fps)
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user