最近在写Ar项目,研究了一段时间Vuforia+zxing实现二维码扫描,走了许多弯路,浪费了不少时间,所以,分享一下代码,方便那些想要用vuforia+zxing来实现二维码扫描同窗。ui
直接贴代码:this
using UnityEngine; using FairyGUI; using ZXing; using ZXing.Client.Result; using Vuforia; using System; //扫描二维码 public class UIScanning : MonoBehaviour { private GObject _ArVerifyQRUI_btn_back_name; private GComponent _mainView; private GLoader _mGloader; private GTextInput _ArVerifyQRUI_et_code_name; private Vuforia.Image.PIXEL_FORMAT m_PixelFormat = Vuforia.Image.PIXEL_FORMAT.RGB888; private bool m_RegisteredFormat = false; private bool m_LogInfo = true; public VuforiaBehaviour vuforia; public static event Action<ParsedResult, string> Scanned = delegate { }; public static event Action<string> ScannedQRCode = delegate { }; public static event Action<string> ScannedBarCode = delegate { }; bool decoding; bool init; BarcodeReader barcodeReader = new BarcodeReader(); void Awake() { UIPackage.AddPackage("fairyui_scan_main/scense_2/ArScanMain"); } void Start() { Global.seleteScene(5); _mainView = this.GetComponent<UIPanel>().ui; _ArVerifyQRUI_btn_back_name = _mainView.GetChild("ArVerifyQRUI_btn_back_name"); _ArVerifyQRUI_btn_back_name.visible = true; _ArVerifyQRUI_btn_back_name.onClick.Add(onClickBack); _mGloader = _mainView.GetChild("ArVerifyQRUI_Iimages").asLoader; _ArVerifyQRUI_et_code_name = _mainView.GetChild("ArVerifyQRUI_et_code_name").asTextInput; vuforia = GameObject.FindGameObjectsWithTag("ARScanningCamera")[0].GetComponent<VuforiaBehaviour>(); } void Update() { if (vuforia == null) return; if (vuforia.enabled && !init) { //Wait 1/4 seconds for the device to initialize (otherwise it seems to crash sometimes) init = true; Loom.QueueOnMainThread(() => { init = CameraDevice.Instance.SetFrameFormat(Vuforia.Image.PIXEL_FORMAT.RGB888, true); }, 0.25f); } if (vuforia.enabled && CameraDevice.Instance != null && !decoding) { var image = CameraDevice.Instance.GetCameraImage(Vuforia.Image.PIXEL_FORMAT.RGB888); if (image != null) { decoding = true; Loom.RunAsync(() => { try { var data = barcodeReader.Decode(image.Pixels, image.BufferWidth, image.BufferHeight, RGBLuminanceSource.BitmapFormat.RGB24); if (data != null) { Loom.QueueOnMainThread(() => { if (data.BarcodeFormat == BarcodeFormat.QR_CODE) { ScannedQRCode(data.Text); if (_ArVerifyQRUI_et_code_name != null) { _ArVerifyQRUI_et_code_name.text = data.Text; } } if (data.BarcodeFormat != BarcodeFormat.QR_CODE) { ScannedBarCode(data.Text); if (_ArVerifyQRUI_et_code_name != null) { _ArVerifyQRUI_et_code_name.text = data.Text; } } // var parsedResult = ResultParser.parseResult(data); // if (target != null) // { // target.SendMessage("Scanned", parsedResult, SendMessageOptions.DontRequireReceiver); //} // Scanned(parsedResult, data.Text); }); } } finally { decoding = false; } }); } } } //返回按钮 private void onClickBack() { Application.LoadLevel(Global.sceneHome); } }
Loom 线程队列管理:线程
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using System.Threading; using System.Linq; //Loom handles threading public class Loom : MonoBehaviour { private static Loom _current; public static Loom Current { get { if (_current == null && Application.isPlaying) { var g = GameObject.Find("Loom"); if (g == null) { g = new GameObject("Loom"); } _current = g.GetComponent<Loom>() ?? g.AddComponent<Loom>(); } return _current; } } void Awake() { if (_current != null && _current != this) { Destroy(gameObject); } else { _current = this; } } private List<Action> _actions = new List<Action>(); public class DelayedQueueItem { public float time; public Action action; public string name; } private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>(); public static void QueueOnMainThread(Action action, float time, string name) { lock (Current._delayed) { if (Current._delayed.Any(d => d.name == name)) return; QueueOnMainThread(action, time); } } public static void QueueOnMainThread(Action action, string name) { QueueOnMainThread(action, 0, name); } public static void QueueOnMainThread(Action action, float time) { if (time != 0) { lock (Current._delayed) { Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action }); } } else { lock (Current._actions) { Current._actions.Add(action); } } } public static void QueueOnMainThread(Action action) { lock (Current._actions) { Current._actions.Add(action); } } public static void RunAsync(Action a) { var t = new Thread(RunAction); t.Priority = System.Threading.ThreadPriority.Normal; t.Start(a); } private static void RunAction(object action) { ((Action)action)(); } List<Action> toBeRun = new List<Action>(); List<DelayedQueueItem> toBeDelayed = new List<DelayedQueueItem>(); void Update() { //Process the non-delayed actions lock (_actions) { toBeRun.AddRange(_actions); _actions.Clear(); } foreach (var a in toBeRun) { try { a(); } catch (Exception e) { Debug.LogError("Queued Exception: " + e.ToString()); } } toBeRun.Clear(); lock (_delayed) { toBeDelayed.AddRange(_delayed); } foreach (var delayed in toBeDelayed.Where(d => d.time <= Time.time)) { lock (_delayed) { _delayed.Remove(delayed); } try { delayed.action(); } catch (Exception e) { Debug.LogError("Delayed Exception:" + e.ToString()); } } toBeDelayed.Clear(); } }