🐡

[Astar]コントラクト備忘録51(Unityからコントラクトアドレスを取得しよう!)

2023/03/29に公開

本日は、UnityとAstarのWASMの連結方法について見ていきます。

大まかな構成としては、websocketのサーバーを立て、polkadot.jsを使って、ブロックチェーンに連携します。

その上で、unityとwebsocketを連結しています。

1 WebSocketサーバーについて

では、コードを見てみましょう。

WebSocket.Server()でポート8080でサーバーをリッスンするようにサーバーを構成しています。

そして、server.onでクライアントとの接続が確立された時に実行されるコールバック関数を定義しています。

具体的にはconnectionイベントが発生した場合に、このコールバック関数が実行されます。


若干修正しました。修正後はこの記事の一番下にコードを載せています。

そして、実際の処理として、connect関数が実行されています。

下のように、コントラクトが取得されていますが、ここでは説明を省略いたします。

2 Unity側のコードについて(C#)

では、次にUnityのコードを見てみましょう。

今回、websocketを使うために、「NativeWebSocket」を使っています。

1) NativeWebSocketのインポートについて

こちらのGithubを使っていきます。
https://github.com/endel/NativeWebSocket

こちらの手順に沿ってやっていきます。

「Window」から「Package Manager」を選択します。

こちらの「+」から、「Add Package From Git URL」を選択します。

GithubのURLを貼り付けて、「Add」で完了です。

2) コードの中身について

では、コードの中身を見てみましょう。

下にあるように、WebSocketのインスタンスを作成し、接続時やエラー発生時などの処理を記述しています。

では、こちらのボタンを押してみます。

このボタンを押すと、こちらの「connect」関数を実行するように設定しています。(設定方法などは今回省略します。)

すると、このように、「websocket.OnOpen」の中身が実行されたことがわかりました。

では、websocketのサーバーの処理も見てみます。

このように、今回コントラクトアドレスを返すように設定しています。

こちらがUnity側の処理です。

メッセージを受け取った場合、文字列に変換し、表示させるようにしています。

このように表示することができました。

今回は以上です。

なお、今回使ったコードは下のものになります。

server.js
const WebSocket = require("ws");

const { ApiPromise, WsProvider } = require("@polkadot/api");
const { ContractPromise } = require("@polkadot/api-contract");

const metadata = require("./metadata.json");

async function connect() {
  // Connect to the local development network
  const provider = new WsProvider("wss://rpc.shibuya.astar.network");
  const api = await ApiPromise.create({ provider });

  const contract = new ContractPromise(
    api,
    metadata,
    "a1MvMiL1VPNKHc6pb8XNAw6fcwh85fc8V3wgocpmJjYK1Tm"
  );

  console.log(contract.address.toHuman());

  return contract.address.toHuman();
}

const server = new WebSocket.Server({ port: 8080 });

server.on("connection", async (socket) => {
  console.log("Connect");
  const contract = await connect();

  console.log("Client connected.");

  socket.send(`Contract Address: ${contract}`);

  socket.on("message", (message) => {
    console.log(`Received message: ${message}`);
    socket.send(`Server received: ${message}`);
  });

  socket.on("close", () => {
    console.log("Client disconnected.");
  });
});

(unityのコード)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using NativeWebSocket;

public class StartMenuManager : MonoBehaviour
{

    WebSocket websocket;
    // Start is called before the first frame update
    void Start()
    {
        // WebSocketクライアントのインスタンスを生成
        websocket = new WebSocket("ws://localhost:8080");

        websocket.OnOpen += () =>
        {
        Debug.Log("Connection open!");
        };

        websocket.OnError += (e) =>
        {
        Debug.Log("Error! " + e);
        };

        websocket.OnClose += (e) =>
        {
        Debug.Log("Connection closed!");
        };

        websocket.OnMessage += (bytes) =>
        {
            Debug.Log("OnMessage!");
            Debug.Log(bytes);

            // getting the message as a string
            var message = System.Text.Encoding.UTF8.GetString(bytes);
            Debug.Log("OnMessage! " + message);
        };

        // Keep sending messages at every 0.3s
        // InvokeRepeating("SendWebSocketMessage", 0.0f, 0.3f);

    }

    // Update is called once per frame
    void Update()
    {
        #if !UNITY_WEBGL || UNITY_EDITOR
        websocket.DispatchMessageQueue();
        #endif
    }

    async void SendWebSocketMessage()
    {
        if (websocket.State == WebSocketState.Open)
        {
        // Sending bytes
        await websocket.Send(new byte[] { 10, 20, 30 });

        // Sending plain text
        await websocket.SendText("plain text message");
        }
    }
    public async void connect(){
        
        // waiting for messages
        await websocket.Connect();
  
    }
}

Discussion