在unity里做扫二维码的功能,虽然有插件,但是移动端UI一般不能自定义,所以后来自已做了一个,直接在c#层扫描解析,UI上就可以自己发挥了。
上代码:
这个是调用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>
- /// 二维码解析工具
- /// 关键函数:
- /// public static QRHelper GetInst() --得到单例
- /// public event Action<string> OnQRScanned; --扫描回调
- /// public void StartCamera(int index) --启动摄像头
- /// public void StopCamera() --停止摄像头
- /// public void SetToUI(RawImage raw,int UILayoutW,int UILayoutH) --把摄像机画面设置到一个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>
- /// 把摄像机画面设置到一个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;
- }
- //在考虑可能旋转的情况下计算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;
- }
- }
调用方式如下,用了pureMVC,可能理解起来有点乱,也不能直接用于你的工程,主要看OnRegister和OnRemove里是怎么启动和停止的,以及RegQRCB、RemoveQRCB、OnQRSCcanned如何注册、移除以及响应扫描到二维码的事件的。在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测试可用。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。