Unity實現(xiàn)多平臺二維碼掃描
在unity里做掃二維碼的功能,雖然有插件,但是移動端UI一般不能自定義,所以后來自已做了一個,直接在c#層掃描解析,UI上就可以自己發(fā)揮了。
上代碼:
這個是調(diào)用zxing的腳本。
using UnityEngine; using System.Collections; using ZXing; using ZXing.QrCode; public class QR { /// <summary> /// 解析二維碼 /// </summary> /// <param name="tex"></param> /// <returns></returns> public static string Decode(Texture2D tex) { return DecodeColData(tex.GetPixels32(), tex.width, tex.height); //通過reader解碼 } public static string DecodeColData(Color32[] data, int w, int h) { BarcodeReader reader = new BarcodeReader(); Result result = reader.Decode(data, w, h); //通過reader解碼 //GC.Collect(); if (result == null) return ""; else { return result.Text; } } /// <summary> /// 生成二維碼 /// </summary> /// <param name="content"></param> /// <param name="len"></param> /// <returns></returns> public static Texture2D GetQRTexture(string content, int len = 256) { var bw = new BarcodeWriter(); bw.Format = BarcodeFormat.QR_CODE; bw.Options = new ZXing.Common.EncodingOptions() { Height = len, Width = len }; var cols = bw.Write(content); Texture2D t = new Texture2D(len, len); t.SetPixels32(cols); t.Apply(); return t; } }
然后是封裝:
using UnityEngine; using System.Collections; using System; using UnityEngine.UI; using System.Timers; /// <summary> /// 二維碼解析工具 /// 關(guān)鍵函數(shù): /// public static QRHelper GetInst() --得到單例 /// public event Action<string> OnQRScanned; --掃描回調(diào) /// public void StartCamera(int index) --啟動攝像頭 /// public void StopCamera() --停止攝像頭 /// public void SetToUI(RawImage raw,int UILayoutW,int UILayoutH) --把攝像機畫面設(shè)置到一個rawimage上并使它全屏顯示 /// </summary> public class QRHelper { public event Action<string> OnQRScanned; private static QRHelper _inst; public static QRHelper GetInst() { if (_inst == null) { _inst = new QRHelper(); } return _inst; } private int reqW = 640; private int reqH = 480; private WebCamTexture webcam; Timer timer_in, timer_out; /// <summary> /// 啟動攝像頭 /// </summary> /// <param name="index">手機后置為0,前置為1</param> public void StartCamera(int index) { StopCamera(); lock (mutex) { buffer = null; tbuffer = null; } var dev = WebCamTexture.devices; webcam = new WebCamTexture(dev[index].name); webcam.requestedWidth = reqW; webcam.requestedHeight = reqH; webcam.Play(); stopAnalysis = false; InitTimer(); timer_in.Start(); timer_out.Start(); } /// <summary> /// 停止 /// </summary> public void StopCamera() { if (webcam!=null) { webcam.Stop(); UnityEngine.Object.Destroy(webcam); Resources.UnloadUnusedAssets(); webcam = null; stopAnalysis = true; timer_in.Stop(); timer_out.Start(); timer_in = null; timer_out = null; } } /// <summary> /// 把攝像機畫面設(shè)置到一個rawimage上并使它全屏顯示 /// </summary> /// <param name="raw">rawimage</param> /// <param name="UILayoutW">UI布局時的寬度</param> /// <param name="UILayoutH">UI布局時的高度</param> public void SetToUI(RawImage raw,int UILayoutW,int UILayoutH){ raw.GetComponent<RectTransform>().sizeDelta = GetWH(UILayoutW,UILayoutH); int d = -1; if (webcam.videoVerticallyMirrored) { d = 1; } raw.GetComponent<RectTransform>().localRotation *= Quaternion.AngleAxis(webcam.videoRotationAngle, Vector3.back); float scaleY = webcam.videoVerticallyMirrored ? -1.0f : 1.0f; raw.transform.localScale = new Vector3(1, scaleY * 1, 0.0f); raw.texture = webcam; raw.color = Color.white; } //在考慮可能旋轉(zhuǎn)的情況下計算UI的寬高 private Vector2 GetWH(int UILayoutW, int UILayoutH) { int Angle = webcam.videoRotationAngle; Vector2 init = new Vector2(reqW, reqH); if ( Angle == 90 || Angle == 270 ) { var tar = init.ScaleToContain(new Vector2(UILayoutH,UILayoutW)); return tar; } else { var tar = init.ScaleToContain(new Vector2(UILayoutW, UILayoutH)); return tar; } } private void InitTimer() { timer_in = new Timer(500); timer_in.AutoReset = true; timer_in.Elapsed += (a,b) => { ThreadWrapper.Invoke(WriteDataBuffer); }; timer_out = new Timer(900); timer_out.AutoReset = true; timer_out.Elapsed += (a,b)=>{ Analysis(); }; } private Color32[] buffer = null; private Color32[] tbuffer = null; private object mutex = new object(); private bool stopAnalysis = false; int dw, dh; private void WriteDataBuffer() { lock (mutex) { if (buffer == null && webcam!=null) { buffer = webcam.GetPixels32(); dw = webcam.width; dh = webcam.height; } } } //解析二維碼 private void Analysis() { if (!stopAnalysis) { lock (mutex) { tbuffer = buffer; buffer = null; } if (tbuffer == null) { ; } else { string str = QR.DecodeColData(tbuffer, dw, dh); tbuffer = null; if (!str.IsNullOrEmpty() && OnQRScanned != null) { ThreadWrapper.Invoke(() => { if (OnQRScanned!=null) OnQRScanned(str); }); } } } tbuffer = null; } }
調(diào)用方式如下,用了pureMVC,可能理解起來有點亂,也不能直接用于你的工程,主要看OnRegister和OnRemove里是怎么啟動和停止的,以及RegQRCB、RemoveQRCB、OnQRSCcanned如何注冊、移除以及響應(yīng)掃描到二維碼的事件的。在onregister中,由于ios上畫面有鏡象,所以把rawimage的scale的y置為了-1以消除鏡像:
using UnityEngine; using System.Collections; using System.Collections.Generic; using PureMVC.Patterns; using PureMVC.Interfaces; /// <summary> /// 掃描二維碼界面邏輯 /// </summary> public class ScanQRMediator : Mediator { AudioProxy audio; public QRView TarView { get { return base.ViewComponent as QRView; } } public ScanQRMediator() : base("ScanQRMediator") { } string NextView = ""; bool isInitOver = false; int cameraDelay = 1; public override void OnRegister() { base.OnRegister(); if (Application.platform == RuntimePlatform.IPhonePlayer) { cameraDelay = 5; } else { cameraDelay = 15; } audio = AppFacade.Inst.RetrieveProxy<AudioProxy>("AudioProxy"); TarView.BtnBack.onClick.AddListener(BtnEscClick); QRHelper.GetInst().StartCamera(0); TarView.WebcamContent.rectTransform.localEulerAngles = Vector3.zero; CoroutineWrapper.EXEF(cameraDelay, () => { RegQRCB(); QRHelper.GetInst().SetToUI(TarView.WebcamContent, 1536, 2048); if (Application.platform == RuntimePlatform.IPhonePlayer) { TarView.WebcamContent.rectTransform.localScale = new Vector3(1, -1, 0); } isInitOver = true; }); UmengStatistics.PV(TarView); //暫停背景音樂 audio.SetBGActive(false); } public override void OnRemove() { base.OnRemove(); TarView.BtnBack.onClick.RemoveListener(BtnEscClick); if (NextView != "UnlockView") { audio.SetBGActive(true); } NextView = ""; isInitOver = false; } bool isEsc = false; void BtnEscClick() { if (isEsc || !isInitOver) { return; } isEsc = true; TarView.WebcamContent.texture = null; TarView.WebcamContent.color = Color.black; RemoveQRCB(); QRHelper.GetInst().StopCamera(); CoroutineWrapper.EXEF(cameraDelay, () => { isEsc = false; if (Application.platform == RuntimePlatform.IPhonePlayer) { ToUserInfoView(); } else { string origin = TarView.LastArg.SGet<string>("origin"); if (origin == "ARView") { ToARView(); } else if (origin == "UserInfoView") { ToUserInfoView(); } else { ToARView(); } } }); } void ToARView() { AppFacade.Inst.RemoveMediator(this.MediatorName); ViewMgr.GetInst().ShowView(TarView, "ARView", null); } void ToUserInfoView() { AppFacade.Inst.RemoveMediator(this.MediatorName); ViewMgr.GetInst().ShowView(TarView, "UserInfoView", null); var v = ViewMgr.GetInst().PeekTop(); var vc = new UserInfoMediator(); vc.ViewComponent = v; AppFacade.Inst.RegisterMediator(vc); } int reg = 0; void RegQRCB() { if (reg == 0) { QRHelper.GetInst().OnQRScanned += OnQRScanned; reg = 1; } } void RemoveQRCB() { if (reg == 1) { QRHelper.GetInst().OnQRScanned -= OnQRScanned; reg = 0; } } bool isQRJump = false; void OnQRScanned(string qrStr) { if (isQRJump) { return; } isQRJump = true; TarView.WebcamContent.texture = null; TarView.WebcamContent.color = Color.black; RemoveQRCB(); QRHelper.GetInst().StopCamera(); NextView = "UnlockView"; CoroutineWrapper.EXEF(cameraDelay, () => { isQRJump = false; AppFacade.Inst.RemoveMediator(this.MediatorName); audio.PlayScanedEffect(); #if YX_DEBUG Debug.Log("qr is :"+qrStr); Toast.ShowText(qrStr,1.5f); #endif ViewMgr.GetInst().ShowView(TarView, "UnlockView", HashtableEX.Construct("QRCode", qrStr, "origin", TarView.LastArg.SGet<string>("origin"))); var v = ViewMgr.GetInst().PeekTop(); var vc = new UnlockMediator(); vc.ViewComponent = v; AppFacade.Inst.RegisterMediator(vc); }); } }
最后,放上zxing.unity.dll,放在plugins里就可以了。
以上代碼5.1.2測試可用。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# 動態(tài)調(diào)用WebService的示例
這篇文章主要介紹了C# 動態(tài)調(diào)用WebService的示例,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-11-11C#實現(xiàn)將json轉(zhuǎn)換為DataTable的方法
這篇文章主要介紹了C#實現(xiàn)將json轉(zhuǎn)換為DataTable的方法,涉及C#操作json及DataTable的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-03-03C#?DataSet結(jié)合FlyTreeView實現(xiàn)顯示樹狀模型數(shù)據(jù)
NineRays.WebControls.FlyTreeView?是?9rays.net?推出的一款功能強大的樹狀模型數(shù)據(jù)顯示控件,本文主要介紹了如何使用其并結(jié)合?DataSet對象進行數(shù)據(jù)顯示,感興趣的可以了解下2024-04-04C#實現(xiàn)子窗體與父窗體通信方法實例總結(jié)
這篇文章主要介紹了C#實現(xiàn)子窗體與父窗體通信方法,實例總結(jié)了常用的四種窗體通信方法,具有一定參考借鑒價值,需要的朋友可以參考下2015-09-09C#實現(xiàn)向數(shù)組指定索引位置插入新的元素值
這篇文章給大家介紹了利用C#實現(xiàn)向數(shù)組指定索引位置插入新的元素值,首先需要定義一個一維數(shù)組,然后修改數(shù)組的長度,從而在其中增加一個元素,需要的朋友可以參考下2024-02-02C# Web應(yīng)用調(diào)試開啟外部訪問步驟解析
本文主要介紹了C# Web應(yīng)用調(diào)試開啟外部訪問的實現(xiàn)過程與方法。具有一定的參考價值,下面跟著小編一起來看下吧2017-01-01