VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • Unity实现多平台二维码扫描

在unity里做扫二维码的功能,虽然有插件,但是移动端UI一般不能自定义,所以后来自已做了一个,直接在c#层扫描解析,UI上就可以自己发挥了。

上代码:

这个是调用zxing的脚本。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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;
  }
}

然后是封装:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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以消除镜像:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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里就可以了。


相关教程