關於 web service, unity, blogger 等軟體工程筆記

QR code generator in Unity

Edit icon 沒有留言
QRCode

需求要在遊戲中顯示 QR code,該 QR code 帶某網站的網址,原先是計畫用工具生成 QR code 後,放入 Unity 當作貼圖使用。

但考慮到這網址可以從遊戲伺服器資料拿到,那為何不用動態產生 QRCode,省去未來網址修改,替換貼圖的麻煩呢?紀錄實作此功能的過程。

QR code,沒實作過,也不懂其圖像規格,因此第一個想法是想直接從網路上,撈現成的函數庫使用,而不是了解規格後自己實作。

很幸運的,在 Github 找到一套可產生 QR code 的函數庫 codebude/QRCoder 可以使用,而且有支援 Unity 的實作。

下載 Github 該專案中的 QRCoder 資料夾內容,直接貼到遊戲專案 (/Assets/Plugins/QRCoder) 中,然後調整以下動作,使得能夠正常編譯:

  • 移除 PayloadGenerator.cs,由於 C# 版本緣故,裡頭實作語法 (Syntax) 無法編譯,又沒運用到裡頭的 Payload (例如產生 Bitcoin 付款連結,產生 Wi-Fi 連結等),所以直接移除

  • 移除 C# project 資料,移除不會用到的 /Properties,.csproj,.dll 等等

  • 移除無法使用的實作,部分實作使用到 Unity Mono C# 所沒有引用的函數庫,例如 System.Drawing,無法編譯且在 Unity 又使用不到,移除 QRCode.cs,SvgQRCode.cs,BitmapByteQRCode.cs,Base64QRCode.cs。

  • 最後僅留下核心檔案 AbstractQRCode.cs,QRCodeData.cs,QRCodeGenerator.cs,以及重要的 Unity 實作 UnityQRCode.cs

  • 修改造成 error CS1061 的錯誤,主因是 .net 版本不同,在 QRCodeGenerator.cs 檔案開頭定義符號 #define NET40 後,編譯錯誤就可解決。或是手動修改那幾段編譯不過的程式碼。

能夠在 Unity 編譯後,使用以下範例程式碼便可在 UI.Image 中顯示動態產生的 QR code 了。

using QRCoder;
using UnityEngine;
using UnityEngine.UI;

// Generate QR code texture
var link = "http://example.com";
var qrGenerator = new QRCodeGenerator();
var qrCodeData = qrGenerator.CreateQrCode(link, QRCodeGenerator.ECCLevel.M);
var qrCode = new UnityQRCode(qrCodeData);
var qrCodeImage = qrCode.GetGraphic(20);

// Create sprite & display
var sprite = Sprite.Create(qrCodeImage, new Rect(0, 0, qrCodeImage.width, qrCodeImage.height), new Vector2(.5f, .5f));
var image = this.GetComponent();
image.sprite = sprite;

QRCodeGenerator.ECCLevel 表示容錯能力 (error correction rate),根據 wiki 資料 分成以下幾種,容錯率越高其圖形越大,一般使用 15% 容錯率:

  • ECCLevel.L (Low),7% 的字碼可被修正
  • ECCLevel.M (Medium),15% 的字碼可被修正
  • ECCLevel.Q (Quartile),25% 的字碼可被修正
  • ECCLevel.H (High),30% 的字碼可被修正

若考慮資源釋放問題,可以利用 using 來釋放:

Texture2D CreateQRCode(string data, QRCodeGenerator.ECCLevel level = QRCodeGenerator.ECCLevel.M)
{
   using (var qrGenerator = new QRCodeGenerator())
   {
      using (var qrCodeData = qrGenerator.CreateQrCode(data, this.level))
      {
         return new UnityQRCode(qrCodeData).GetGraphic(20);
      }
   }
}
使用 App 掃描 QRCode

利用別的 App 掃描 QRCode 測試

沒有留言: