🔰

【Flutter × 初心者】Live2D サンプルキャラを Unity で表示!flutter_unity_widget 動作編2

2024/10/10に公開

はじめに

実装内容は下記です!

  • Unity側でボタンを押下時にFlutter側でアクションを検知する。

onUnityMessageを使います!

主なプログラム経験

  • 会社員時代
    • OracleDB 5年
    • Java 5年
  • フリーランス時代
    • supabse 2年
    • nextjs 2年
    • hubspot 2年

対象者

  • Android開発のみ
  • 同じぐらいのflutter初心者

書き方や対処法も独自で対応した部分もあるので別に良い方法があれば教えていただきたいです。
それではやっていきましょう。

開発環境

今までのページと同じです!
https://zenn.dev/tiel/articles/0613c6d0d4497c

  • OS
    • Mac M3
  • IDE
    • Visual Studio Code
  • Flutter
    • version 3.22
        - Flutterで使用するパッケージ
      • flutter_unity_widget: ^2022.2.1
  • Unity
    • 2022.3.46f1
    • unityで使用するパッケージファイル
      • CubismSdkForUnity-5-r.2.unitypackage
      • fuw-2022.2.0.unitypackage

Flutter側の実装

確認用のtoastライブラリを入れる

値表示の確認用にtoastを使えるようにします。

dependencies:
  flutter:
    sdk: flutter
  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.6
  flutter_unity_widget: ^2022.2.1
+ oktoast: ^3.3.2
flutter pub get

OKToastウィジェットを使えるようにラップします。

void main() {
  runApp(
+  const OKToast(
         child: MaterialApp(home: UnityDemoScreen()),
+        ),
  );
}

Unityの値を検知するコードの実装

onUnityCreatedを使用します。

import 'package:flutter/material.dart';
import 'package:flutter_unity_widget/flutter_unity_widget.dart';
import 'package:oktoast/oktoast.dart';

void main() {
  runApp(
    const OKToast(
        child: MaterialApp(
      home: UnityDemoScreen(),
    )),
  );
}

class UnityDemoScreen extends StatefulWidget {
  const UnityDemoScreen({super.key});

  @override
  State<UnityDemoScreen> createState() => _UnityDemoScreenState();
}

class _UnityDemoScreenState extends State<UnityDemoScreen> {
  static final GlobalKey<ScaffoldState> _scaffoldKey =
      GlobalKey<ScaffoldState>();
  UnityWidgetController? _unityWidgetController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: SafeArea(
        bottom: false,
        child: WillPopScope(
          onWillPop: () async {
            // Pop the category page if Android back button is pressed.
            return true;
          },
          child: Container(
              color: Colors.yellow,
              child: Column(
                children: [
                  Expanded(
                    child: UnityWidget(
                      onUnityCreated: onUnityCreated,
+                     onUnityMessage: onUnityMessage,
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      _sendPlayMotionMessage();
                    },
                    child: const Text('応援する'),
                  ),
+                // toastのテスト用に実装します。
+                ElevatedButton(
+                   onPressed: () {
+                     showToast("This is an OKToast!");
+                   },
+                   child: const Text('toastテストボタン'),
+                 ),
                ],
              )),
        ),
      ),
    );
  }

  void _sendPlayMotionMessage() {
    _unityWidgetController?.postMessage(
        'Koharu', // Unity側のゲームオブジェクト名
        'PlayAnimation', // Unity側のメソッド名
        'body'); // 引数
  }

  // Callback that connects the created controller to the unity controller
  void onUnityCreated(controller) {
    _unityWidgetController = controller;
  }

+ void onUnityMessage(data) {
+   showToast(data);
+ }
}

トーストの動作確認

中身はまだ通信実装してませんが、メッセージが出るかをテストします。

flutter run

テスト用に実装したボタンを押します!
(すぐ消えてしまうため急いでスクショしました...)

Unity側の実装

次にUnity側からアクションを送ります!

READMEファイルは下記のように書いてありました。

Unity-Flutter
Select the GameObject that should execute the communication and go to Inspector > Add Component > Unity Message Manager.
Create a new MonoBehaviour subclass and add to the same GameObject as a script.
On this new behaviour, call GetComponent<UnityMessageManager>() to get a UnityMessageManager.
Use the method SendMessageToFlutter to send a string. Receive this message using the onUnityMessage callback of a UnityWidget.

和訳しました。順にやっていきます。

  1. 通信を実行する対象のGameObjectを選択し、インスペクタで「Add Component」ボタンをクリックして、「Unity Message Manager」を追加します。
  2. 新しいMonoBehaviourクラスを作成し、同じGameObjectにスクリプトとして追加します。
  3. この新しいクラス内で、GetComponent<UnityMessageManager>()を呼び出して、UnityMessageManagerを取得します。
  4. SendMessageToFlutterメソッドを使用して、文字列をFlutterに送信します。Flutter側では、UnityWidgetのonUnityMessageコールバックを使ってこのメッセージを受信します。

1.GameObject(ボタン)にUnity Message Managerをアタッチ

Flutterに通信するボタンを用意します。

少し間抜けですが、頭にButtonを用意し適当に位置を調整します。

用意したボタンにUnity Message Managerをアタッチします。
Unity Message ManagerというのがあるらしいのでAdd Componentから検索し設定します。

2.Unity Message Managerに対応するスクリプトを作成

今回は「KoharuMessageManagerScript」のスクリプファイルを作成します。
/Assets/Scripts

/Assets/Scripts/KoharuMotionScript #以前作ったファイル
+              /KoharuMessageManagerScript

Scriptの中身を書いていきます。
KoharuMessageManagerScript

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FlutterUnityIntegration; // ★これを忘れずに
public class KoharuMessageManagerScript : MonoBehaviour
{
    private UnityMessageManager messageManager;

    void Start()
    {
        messageManager = GetComponent<UnityMessageManager>();
    }
    // Flutterにメッセージを送信するメソッド
    public void SendMessageToFlutter()
    {
        if (messageManager != null)
        {
            // ここで文字列メッセージを送信
            messageManager.SendMessageToFlutter("Hello from Unity!");
            Debug.Log("Flutterにメッセージを送信しました: Hello from Unity!");
        }
        else
        {
            Debug.LogError("UnityMessageManagerが見つかりませんでした");
        }
    }
}

3. 作成したスクリプトをButtonにアタッチ

ButtonのAdd ComponentからKoharuMessageManagerScriptを探しアタッチします。
最終的にアタッチした内容は画像のとおりです。

4. GameObject(ボタン)にクリックリスナーを設定

ButtonのinspectorにOn Clickの欄があります。
画像のようにGameObjectをドラッグ&ドロップしてください。

その後、No Functionをクリックするとアタッチしてるスクリプトが選べます。
今回は、 KoharuMessageManagerScript > SendMessageToFlutter です。
SendMessageToFlutterはメソッド名です。

これで設定完了です。

Unityプロジェクトのビルドをします。

今まで通り、ビルドをします。

動かしてみる

これで動かせるようになったはずなので確認します!

ボタンがめちゃくちゃ小さいですね...
ただメッセージが「Hello from Unity!」となってるので成功です!

やってみた結果

Button部分のOnclickの指定方法が手間取りました。
日々勉強になります。
今は、絵の勉強もし始めてるので
忘れないように定期的にflutter x unity のいづれかについて
書ければいいなと思ってます。
拙い文章でしたがここまで読んでいただきありがとうございました。
ではまた。

Discussion