unity多平台二维码扫描(可自定义UI)

在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里就可以了,http://pan.baidu.com/s/1gfv5bkJ

以上代码5.1.2测试可用。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值