• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Unity实现多平台二维码扫描

c# 搞代码 4年前 (2022-01-09) 24次浏览 已收录 0个评论

在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)=>{
  <div>本文来源gaodai.ma#com搞##代!^码7网</div>    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;
  }
}

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Unity实现多平台二维码扫描
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址