可用於PC或Android平台
這篇會使用到截圖(Texture2D的ReadPixels方法),可以參考我的這篇文章認識一下這個方法的參數作用
產生QR Code的方法請看這篇
先來下載ZXing並解壓縮,將 zxing.unity.dll 放入專案內的任意位置(該dll為於 ZXing\unity\zxing.unity.dll )
或到官方Github下載最新版
在此我示範兩種方法:「第一種為『靜態掃描』(直接將圖片放到Scene上並顯示出來),第二種為『動態掃描』(開啟攝影機鏡頭來掃描)」
P.S.這篇文章會使用到StartCoroutine和yield return這兩個方法和關鍵字,這兩個的意思可以看這篇文章
第一種、靜態掃描
開啟一個新的Unity專案,從 GameObject → 2D Object → Sprite 新增一個Sprite
然後將這個QR Code放入專案內(命名為Hello,該QR Code內容為"Hello World")
到Unity內,點選該圖片檔案,然後在Inspector將紅色框選的地方改為 Sprite(2D and UI) 後,按下Apply
之後點選剛剛新增的 New Sprite,將Hello檔案拖曳到Sprite欄位內
都完成後看到的Game就像這樣
開始編寫程式碼!
新增一個C# script,命名為QRCode
using UnityEngine;
using System.Collections;
using ZXing;
using ZXing.QrCode;
public class QRCode : MonoBehaviour
{
void Start ()
{
StartCoroutine(scan());
}
private IEnumerator scan()
{
Texture2D t2D = new Texture2D(Screen.width, Screen.height);//掃描後的影片儲存大小,越大會造成效能消耗越大
yield return new WaitForEndOfFrame();//等待Game影像繪製完畢
BarcodeReader reader = new BarcodeReader();//ZXing的解碼物件
t2D.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0, false);//掃描的範圍,設定為整個Game影像。
t2D.Apply();//開始掃描
Result res = reader.Decode(t2D.GetPixels32(), t2D.width, t2D.height);//選擇剛剛新增的圖片進行解碼,並將解碼後的資料回傳
Debug.Log(res.Text);//將解碼後的資料列印出來
}
}
將該腳本拖曳到任意物件上(我將其拖曳到Camera上,也可以拖曳到New Sprite上)後,按下執行!
第二種、動態掃描
開啟新專案,只留下Camera
新增一個C# script,命名為scan_QRCode
開始編寫程式碼!
using UnityEngine;
using System.Collections;
using ZXing;
public class scan_QRCode : MonoBehaviour
{
private WebCamTexture myCam;//接收攝影機返回的圖片數據
private BarcodeReader reader = new BarcodeReader();//ZXing的解碼
private Result res;//儲存掃描後回傳的資訊
private bool flag = true;//判斷掃描是否執行完畢
void Start ()
{
StartCoroutine(open_Camera());//開啟攝影機鏡頭
}
void OnGUI()
{
if (myCam != null)//若有攝影機則將攝影機拍到的畫面畫出
{
if (myCam.isPlaying == true)//若攝影機已開啟
{
GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), myCam);//將攝影機讀取到的影像繪製到螢幕上
if (flag == true)//若掃描已執行完畢,則再繼續進行掃描,防止第一個掃描還沒結束就又再次掃描,造成嚴重的記憶體耗盡
{
StartCoroutine(scan());
}
}
}
}
private IEnumerator open_Camera()
{
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam); //授權開啟鏡頭
if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
//設置攝影機要攝影的區域
myCam = new WebCamTexture(WebCamTexture.devices[0].name, Screen.width, Screen.height, 60);/* (攝影機名稱, 攝影機要拍到的寬度, 攝影機要拍到的高度, 攝影機的FPS) */
myCam.Play();//開啟攝影機
}
}
private IEnumerator scan()
{
flag = false;//掃描開始執行
Texture2D t2D = new Texture2D(Screen.width, Screen.height);//掃描後的影像儲存大小,越大會造成效能消耗越大,若影像嚴重延遲,請降低儲存大小。
yield return new WaitForEndOfFrame();//等待攝影機的影像繪製完畢
t2D.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0, false);//掃描的範圍,設定為整個攝影機拍到的影像,若影像嚴重延遲,請降低掃描大小。
t2D.Apply();//開始掃描
res = reader.Decode(t2D.GetPixels32(), t2D.width, t2D.height);//對剛剛掃描到的影像進行解碼,並將解碼後的資料回傳
//若是掃描不到訊息,則res為null
if (res != null)
{
Debug.Log(res.Text);//將解碼後的資料列印出來
}
flag = true;//掃描完畢
}
void OnDisable()
{
//當程式關閉時會自動呼叫此方法關閉攝影機
myCam.Stop();
}
}
完成後將腳本拖曳到Camera上後,點選執行!

您好,如果一直运扫描程序,会出现pc内存不断增加,最后导致死机,请问这个是什么原因?谢谢您了。
(中國那邊有些專有名詞我不太清楚,所以專有名詞我就使用英文敘述) 因為Unity的特性是按照順序重複呼叫指定的Method,不管上個Method是否有執行完畢都會一直呼叫,造成stack overflow 有個簡單的方式...讓Method呼叫的頻率降低 將 if (flag == true) { StartCoroutine(scan()); } 丟到FixedUpdate()內,然後設定多久呼叫一次即可(請記得每次執行完scan()時手動Destory掉Texture2D物件)
謝謝你!!!幫上大忙了 不然只有檔案卻不知道怎麼使用超困擾的
想請問一下如果我要將掃描的螢幕轉成直立的,或者是隨手機翻轉,應該怎麼處理呢? 因為我測試後好像只能拿橫的掃描,手機如果拿直的他顯示的是翻轉90度的畫面。 謝謝~
我目前想到的解決方法是:「檢測陀螺儀的x, y, z座標,然後判斷現在手機是直立、倒立、左橫、右橫,之後旋轉整個顯示的畫面。」 不過我沒出現你所說的那個問題呢....@_@"
您好我是問上一個問題的人,可不可以麻煩您把過程拍成影片或實際測試畫面截圖讓我看一下~謝謝 我在想會不會是版本問題,或是可能我照著教學作但漏調整了一些小地方。 再次謝謝您~
那可能要麻煩您等個幾天喔,我最近很忙,最快可能要到星期5才有時間做。
您好, 請教一個問題,若 QRCode 是一個連結網址, Scan QRCode,Scan到QRCode後,自動開啟連結網址,要怎麼做呢? 另可以內嵌WebView,Scan 到 QRCode 就在WebView開啟 連結網址,可以嗎? 謝謝!!
可以~~ 把掃描到的網址傳到Android端去開啟 http://www.xuanyusong.com/archives/1418
你好~ 請問一下,我是到這個問題 IndexOutOfRangeException: Array index is out of range. scan_QRCode+c__Iterator0.MoveNext () (at Assets/scan_QRCode.cs:38)
是不是我在哪個方面漏掉了些什麼?還是?
給一下你在38行的程式碼... 看那個錯誤訊息是「試圖存取超出陣列範圍資料」所造成的錯誤
你好~38行是: myCam = new WebCamTexture(WebCamTexture.devices[0].name, Screen.width, Screen.height, 60); 請問有哪邊錯誤嗎?
你的電腦是不是沒有攝影機(Webcam)..........
您好, 感謝您的回覆, 但拙學依您上面的步驟, 卻無法 Scan QRCODE,手機甚至會當機, 相機畫面也旋轉90度,Scan QRCode也沒反應,如何傳到 Android 呢? 或者可以直接在 Unity 裡使用 Android QRCode 的程式並開啟 WebView 呢?
用Eclipse或Android去Debug,看錯誤訊息是什麼。
不好意思,我電腦上沒有攝影機, 但是我放到手機上就會變成黑屏,可以請問這是什麼問題嗎?
用Eclipse或Android去Debug,看錯誤訊息是什麼。
不好意思 if (flag == true) { StartCoroutine(scan()); } 放到FixedUpdate()裡面 這部分一直失敗 想請教該怎麼用 謝謝你
有錯誤訊息嗎?還是無法成功動作? 錯誤訊息的話請貼出來 若無法成功動作,在scan()內加入Debug.Log,隨便印個字串測試有沒有跑到這個method內
void FixedUpdate() { if (flag == true) { StartCoroutine(scan()); } } 不好意思 請問是這樣放嗎
YES
void OnGUI() { if (myCam != null) { if (myCam.isPlaying == true) { GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), myCam); } } } void FixedUpdate() { if (flag == true) { StartCoroutine(scan()); } } 執行之後顯示The referenced script on this Behaviour (Game Object 'Main Camera') is missing!
按照字面意思,檢查你的main camera上的script是否被其他的code所拿掉
不好意思 執行完程式 電腦會卡卡的 不知道是電腦的關係 還是程式有問題 因為也沒錯誤訊息跳出><
可參考1樓的問答
您好,已將ZXing的dll檔移至Unity的Library資料夾中,但腳本似乎讀取不到,想請問是甚麼問題@@
新版的Unity需移動至Plugins資料夾內
請問將APP導入手機後鏡頭歪斜且非常延遲,有甚麼解決方法? 已將 void FixedUpdate() { if (flag == true) { StartCoroutine(scan()); } } 新增至code中
請問 有時候 res = reader.Decode(t2D.GetPixels32(), t2D.width, t2D.height); 會出錯 nullreferenceexception: object reference not set to an instance of an object 但是webcam 是一直在執行的 只是 t2D 貼圖畫面是卡住的 該如何解決
前面多個判斷式判斷t2d是否為null試試看執行結果
您好 我是使用靜態掃描 執行時出現:NullReferenceException: Object reference not set to an instance of an object 請問該怎麼解呢?感謝