สร้างเกมบน Telegram Mini App และเชื่อมต่อกระเป๋า Telegram Wallet ด้วย Unity3D แบบไม่รุงรัง

ผมเขียนเกมบน Unity3D มาเป็นสิบปีแล้วครับ แต่ทุกวันนี้ก็ยังมีสิ่งท้าทายมากมาย เมื่อผมเริ่มหันมาเข้าสู่วงการ เกมในโลกคริปโต หรือที่เรารู้จักกันใน DeFi Game หรือ Game Fi นั่นแหละ สิ่งที่แตกต่างมากๆ สำหรับเกมแบบอื่นๆคือมันต้องเชื่อมต่อกระเป๋า Web3 ได้ ซึ่งแน่นอนเราจำเป็นต้อง build เป็น WebGL คือเป็นเกมที่รันบนเว็บ และหลักการณ์ของ WebGL คือเอาตัวเกมที่รันด้วย UnityEngine ไปวางในหน้า HTML และเรียกมันขึ้นมา ข้อดีคือมันสามารถเล่นที่ไหนก็ได้โดยไม่ต้อง install ลงเครื่อง ส่วนข้อเสียใหญ่ๆเลยของ WebGL คือมันมีปัญหากับ Browser แต่ละรุ่นแตกต่างกันไป โดยเฉพาะ Safari บน iOS, iPad OS มันไม่รองรับครับ และ Network Library ของ C#.net บางตัวมันก็ไม่รองรับครับ เราจึงต้องใช้พวก UnityWebRequest แทนถึงจะทำงานได้ และมันไม่รองรับ Task ต้องใช้ Coroutine เท่านั้นเป็นต้น แต่นั่นไม่ใช่ปัญหา ปัญหาที่แท้จริงคือ Lib ที่เราเอามาใช้ มันรุงรัง และบางทีเราก็แกะไม่ออกอีกต่างหาก

ผมลองใช้ Telegram mini app lib ที่อยู่ใน Unity Assets Store และตัว TonConnect SDK for Unity แล้วนะครับ แต่ผลที่ได้คือผมไม่รู้ว่าต้องไปแก้อะไรตรงไหน แค่จะหาว่า Connect Wallet แล้วเอา address ของผู้ใช้งานมาแสดงใน UI นี่ก็ยังยากเลยครับ เพราะถ้าลองไปโหลดมาใช้ ก็จะรู้ว่า Code ตัวอย่างเขียนไว้อลังการมาก อลังแบบหาจุดเริ่มต้นไม่ได้เลยทีเดียว ทั้งๆ ที่จริงๆ มันง่ายแค่ 5 บรรทัดเอง และที่สำคัญคือมันมี Assets ที่เราไม่ใช้พ่วงมาเยอะมากจนโปรเจคจะหนักมาก มีทั้ง lib สร้าง QR Code ที่ไม่รู้มีมาทำไป ต่อกระเป๋าได้ Telegram มันก็สร้างให้เองอยู่แล้ว แล้วผมทำอย่างไร

Back to basic ครับ เทคโนโลยีมันรองรับอะไรให้ไปหาที่ตรงนั้น

สิ่งที่เราควรรู้ก่อนเกี่ยวกับ Unity3D
1. Unity WebGL รองรับการเรียกใช้งาน JavaScrib ได้ โดยทั้ง Telegram และ TON มี online lib ในรูปแบบ .js ให้เรียกใช้อยู่แล้ว แต่เราต้องเขียน .jslib ในโปรเจคเพื่อเชื่อมโยงให้ Unity เรียกใช้งาน JavaScript ใน HTML ได้
2. HTML อาจโหลด .js ไม่ทันหรืออาจจะติด CORS ได้อันนี้ต้องไปเซตอัพฝั่ง Sever ให้ดี

สร้าง Mini App ใน Telegram
ไปที่ Telegram และเพิ่มคุณพ่อเป็นเพื่อน @BotFather จากนั้นส่ง /start ไปให้คุณพ่อ แล้วคุณพ่อจะบอกว่าทำอย่างไร โดยขั้นตอนง่ายมากครับ ให้ทำตามนี้เลย
1. ส่ง /newbot ไปให้คุณพ่อ คุณพ่อจะถามว่าอยากให้บอทชื่ออะไรนะ ให้เราตั้งชื่อโดยลงท้ายด้วย bot แล้วส่งไปเช่น mynamebot ห้ามมีเครื่องหมายพิเศษ หรืออาจจะใช้ myname_bot ได้เช่นกัน
2. หลังจากสร้างเสร็จคุณพ่อจะให้ key เรามาเรียกว่า app token จะอยู่ในรูปแบบของ 125556… : AEVEds….Scde_vsde ซึ่งจะต้องเอาไว้ใช้ในการเรียก api ของ Telegram ครับ
3. ส่ง /mybot ไปหาคุณพ่อแล้วจะมีเมนู Enable Mini App ให้เลือกเมนูนี้ คุณพ่อจะถามว่า url ที่เราวางเกมไว้คือที่ไหน ก็ให้คุณพ่อไป เท่านี้ก็เสร็จแล้วครับ ง่ายๆ ที่เหลือจะปรับแต่งอะไรก็ไปถาม /start กับคุณพ่อเอานะครับ

สร้าง Unity Project
1. สร้าง Unity Project โดยเลือก Platform เป็น WebGL
2. หา WebGL Template มาลง เนื่องจากของที่ Unty ให้มามันแก้ยากและหาที่เก็บยาก ผมแนะนะ Better2020 ซึ่งไปดาวน์โหลดได้ฟรีที่ https://github.com/yepMad/unity-2020-better-webgl-template ที่แนะนำเพราะคลีนดีและเขาจะ Auto Scale เกมเราได้อย่างเนียนๆ

เชื่อมต่อกับ Telegram
1. เข้าไปใน WebGL Template ที่เราเลือกมา แล้วหา index.html
2. ในส่วนของ Header ให้ใส่ scr ของ Telegram เข้าไปดังนี้

<head>
<script src=”https://telegram.org/js/telegram-web-app.js”></script>
</head>

3. ใน Unity สร้างไฟล์ .jslib ขึ้นมา ผมสมมติว่าใช้ Telegram.jslib
4. เขียน function เชื่อต่อกับ Telegram โดยผ่าน jslib ตัวอย่างผมจะเอาข้อมูลของผู้ใช้งานมาแสดง ผมจะเขียนโดยใช้ function แบบนี้

mergeInto(LibraryManager.library, {
    GetTelegramUserData: function () {
        if (typeof Telegram !== 'undefined' && typeof Telegram.WebApp !== 'undefined') {
            Telegram.WebApp.ready(); <-- เรียกให้ app ทำงานก่อน
            var initData = Telegram.WebApp.initDataUnsafe; <-- เรียกข้อมูลได้เลย
            var user = initData.user;

            if (user) {
                var userData = {
                    id: user.id,
                    is_bot: user.is_bot || false,
                    first_name: user.first_name || "",
                    last_name: user.last_name || "",
                    username: user.username || "",
                    language_code: user.language_code || "",
                    is_premium: user.is_premium || false,
                    photo_url: user.photo_url || "",
                    auth_date: initData.auth_date || "",
                    hash: initData.hash || ""
                };

                // Send success message to Unity with user data as JSON
                SendMessage("TelegramMiniApp", "OnTelegramUserDataSuccess", JSON.stringify(userData));
            } else {
                // Send error message to Unity
                SendMessage("TelegramMiniApp", "OnTelegramUserDataError", "No user data found");
            }
        } else {
            // Send error message to Unity if Telegram WebApp SDK is not available
            SendMessage("TelegramMiniApp", "OnTelegramUserDataError", "Telegram WebApp SDK is not available");
        }
    }
});

เราจะใช้การส่งข้อมูลไปให้ Unity โดยผ่าน SendMessage โดย parameter แรกคือชื่อ GameObject ที่เราเอา Script ไปฝังไว้ ต้วที่ 2 คือ ชื่อ method ที่เราใช้รับค่าใน Unity และสุดท้ายคือ ข้อมูลที่จะส่งไป นั่นคือ json หรือ error message

5. สร้างคลาสมารับ ใน Unity สมมติผมให้ชื่อว่า TelegramMiniApp.cs

using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;
using Newtonsoft.Json;

public class TelegramMiniApp : MonoBehaviour
{
    // Reference to the UI Text element to display the user data or error messages
    public Text userDataText;

    // DllImport to call the GetTelegramUserData function from the .jslib
    [DllImport("__Internal")]
    private static extern void GetTelegramUserData();

    private void Start()
    {
        //FetchTelegramUserData();
    }

    // Call this method to start fetching the Telegram user data
    public void FetchTelegramUserData()
    {
        // Pass the name of this GameObject to the .jslib function so it can send messages back
        GetTelegramUserData();
    }

    // This method is called when the Telegram user data is successfully received
    public void OnTelegramUserDataSuccess(string userDataJson)
    {
        TelegramUser userData = JsonConvert.DeserializeObject<TelegramUser>(userDataJson);
        GameData.gameUser = userData;

        Debug.Log("User data received: " + userDataJson);
        if (userDataText)
        {
            userDataText.text = "User Data: " + userDataJson;
        }
    }

    // This method is called when there is an error getting the Telegram user data
    public void OnTelegramUserDataError(string errorMessage)
    {
        Debug.LogError("Error fetching user data: " + errorMessage);
        userDataText.text = "Error: " + errorMessage;
    }
}

public class TelegramUser
{
    public int id { get; set; }
    public bool is_bot { get; set; }
    public string first_name { get; set; }
    public string last_name { get; set; }
    public string username { get; set; }
    public string language_code { get; set; }
    public bool is_premium { get; set; }
    public string photo_url { get; set; }
    public long auth_date { get; set; }
    public string hash { get; set; }
}

ข้อสังเกตคือ ชื่อ function ที่อยู่ใต้ [DllImport(“__Internal”)] ต้องเหมือนกันกับใน .jslib และ ชื่อ function ในการ handle ว่าสำเร็จหรือไม่จะต้องเหมือนกับตัวที่อยู่ใน SendMessage

ก็จบแล้วครับสำหรับ Telegram อยากได้อะไรเพิ่มก็ไปเขียน function เพิ่มใน jslib และก็ import เข้ามาเหมือนตัวอย่างได้เลยครับ

*หมายเหตุ NewtonSoft.json อาจจะใช้ ตัวอื่นในการ Parse ก็ได้นะครับ แล้วแต่ถนัด

ส่วนการเชื่อมต่อ TON หรือกระเป๋าผมขอแยกเป็นอีกหัวข้อนะครับ

By admin

Leave a Reply

Your email address will not be published. Required fields are marked *