【Unity】AppUI×ClaudiaでMVVMを意識してチャットアプリをつくる 4章 アプリ実装編

# はじめに
この記事は3章の続きです。
まだ読んでいない人は3章から読まれることを推奨します。

この章では1章2章で説明したことを踏まえて実際にチャットアプリを実装していこうと思います。
記事を通じて疑問点があれば、ぜひフィードバックをください。

1章 [設計説明編](https://qiita.com/garume/items/d3edba72548f51108e7c)
2章 [AppUI編](https://qiita.com/garume/items/9e83eb7a3ce7b8c12594)　
3章 [MVVM実装編](https://qiita.com/garume/items/21840bc9edd70f40503b)
4章 [アプリ実装編](https://qiita.com/garume/items/5a26324cbbbeb2d32dc0)
5章 [Middleware編](https://qiita.com/garume/items/3f4c2f4b2de04b602e58)


# アプリの実装
前章まででMVVMまで実装しました。
次はこれをアプリとして動かしていきたいと思います。

以下のようにファイルを作成してください。
```diff
Claudia
  ├── SampleResources
  │   ├── Styles
+ │   │   ├── ClaudiaPanel.asset
+ │   │   ├── ClaudiaTheme.tss
  │   │   └── MainPage.uss
  │   └── Views
  │       └── MainPage.uxml
  ├── Scripts
  │   ├── Runtime
  │   │   ├── Models
  │   │   │   ├── Actions.cs
  │   │   │   ├── AppState.cs
  │   │   │   └── Reducers.cs
  │   │   ├── Services
  │   │   │   ├── ILocalStorageService.cs
  │   │   │   ├── IStoreService.cs
+ │   │   │   ├── LocalStorageService.cs
  │   │   │   ├── MockStorageService.cs
  │   │   │   └── StoreService.cs
  │   │   ├── ViewModels
  │   │   │   ├── IMainViewModel.cs
  │   │   │   ├── MainViewModel.cs
  │   │   │   └── MockMainViewModel.cs
  │   │   ├── Vuiew
  │   │   │   └── MainPage.cs
+ │   │   ├── ClaudiaApp.cs
+ │   │   ├── ClaudiaAppBuilder.cs
  │   │   └── ClaudiaUiToolKit.asmdef
  │   └── Tests
  │       ├── Editor
  │       │   ├── ClaudiaApp.Test.Editor.asmdef
  │       │   └── MainPage.stories.cs
  │       └── Runtime
  │           ├── ViewModels
  │           │   └── MainViewModelTest.cs
  │           └── ClaudiaApp.Test.asmdef
+ └── Claudia.unity
```

`ClaudiaTheme.tss`はUnityから作成することができます。
`Assets → Create → UI Toolkit → TSS Theme File`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704747/a6027609-9560-e0ec-c2da-d0d38c47e648.png)

以下のように設定にしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704747/8945a325-2088-6b52-d116-4c0bb2a48b72.png)

AppUIに関してはAssets以下に含まれておらずドラッグアンドドロップで参照する必要があるので注意してください。

`ClaudiaPanel.asset`は同様にUnityから作成することができます。
`Assets → Create → UI Toolkit → TSS Theme File`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704747/858633e9-96cf-49ee-d792-6228cb7eb3af.png)

以下のように設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704747/0288d0a5-8cea-d672-b481-6e2b082d3e8e.png)


次にスクリプトの実装に移っていきます。

`LocalStorageService.cs`を記述します。

```csharp
using UnityEngine;

namespace ClaudiaApp.Services
{
    public class LocalStorageService : ILocalStorageService
    {
        public T GetValue<T>(string key, T defaultValue = default)
        {
            if (PlayerPrefs.HasKey(key))
            {
                var json = PlayerPrefs.GetString(key);
                return JsonUtility.FromJson<T>(json);
            }

            SetValue(key, defaultValue);
            return defaultValue;
        }

        public void SetValue<T>(string key, T value)
        {
            var json = JsonUtility.ToJson(value);
            PlayerPrefs.SetString(key, json);
        }
    }
}
```

LocalStorageServiceの実装では、PlayerPrefsを利用してデータの永続化を実現しています。これにより、アプリケーションの再起動後もユーザーの設定が保持されます。

`ClaudiaApp.cs`を記述します。

```csharp
using ClaudiaApp.View;
using Unity.AppUI.MVVM;

namespace ClaudiaApp
{
    public class ClaudiaApp : App
    {
        public ClaudiaApp(MainPage page)
        {
            mainPage = page;
        }
    }
}
```

`ClaudiaAppBuilder.cs`を記述します。
```csharp
using ClaudiaApp.Services;
using ClaudiaApp.View;
using ClaudiaApp.ViewModels;
using Unity.AppUI.MVVM;
using UnityEngine.UIElements;

namespace ClaudiaApp
{
    public class ClaudiaAppBuilder : UIToolkitAppBuilder<ClaudiaApp>
    {
        public VisualTreeAsset MainPageTemplate;

        internal static ClaudiaAppBuilder Instance { get; private set; }

        protected override void OnConfiguringApp(AppBuilder builder)
        {
            base.OnConfiguringApp(builder);
            Instance = this;

            builder.services.AddSingleton<ILocalStorageService, LocalStorageService>();
            builder.services.AddSingleton<IStoreService, StoreService>();

            builder.services.AddTransient<IMainViewModel, MainViewModel>();
            builder.services.AddTransient<MainPage>();
        }
    }
}
```

ここで依存関係を解消します。
これにてスクリプトの記述は終わりです。
あとはシーンにUIDocumentとClaudiaAppBuilderを置くだけで内部実装がよしなにやってくれます。

## シーンの実装

`Claudia Scene`を開いてください。
シーン内に`UIDocument`ゲームオブジェクトを作成しましょう。
その後二つのコンポーネントをアタッチしてください。
- UI Document
- Claudia App Builder

以下のようになればオーケーです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704747/4f576454-dcd2-e53c-c2f5-cd58aceeb574.png)

ここまでできたら、シーンを再生してみてください。
Viewが表示されるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704747/2db4c7dd-f3eb-e89b-92ec-8bcf74c55444.png)

表示がおかしい場合はUSSやMainPageに不具合のある可能性が高いです。StoryBookを見直してみましょう。

次にClaudeとチャットしてみましょう。
![7f22983ac9efcaeb624cbf25e04dd9a0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704747/fb650c1b-865a-abf7-6cf2-b0839c062e24.gif)

ボタンを押下して返信が返ってくれば成功です。
帰ってこない場合はStateやViewModelに異常があります。TestRunnerでテストしてみて異常を見つけましょう。

ここまでできればチャットアプリの完成です。
もちろんこれ以上にできることはたくさんあります。
- APIKeyを動的に変更する機能
- 出力をRoleごとに色分けする機能
- 履歴を消去する機能

これらの機能拡張は手続き的に書いた時よりも楽に追加できるはずです。
ぜひ試してみてください。(テストも忘れずに)

もちろんビルドも通るので試してみてください。

# おわりに

1~4章と長い記事を読んでいただきありがとうございました。
Unity上でアプリを作成できるフレームワークAppUIとClaudiaを利用してチャットアプリを作成してみました。
稚拙な部分もあったかと思いますが、役に立てたなら幸いです。
間違い等ありましたら、コメントしていただけると嬉しいです。

筆者は普段、Unity上で動く2DゲームエンジンNebulaを開発しています。
X(旧Twitter)に進捗を上げていますのでそちらも見ていただけると喜びます。

最後になりますが、改めて読んでいただきありがとうございました。
では！ 快適なUIToolkit Lifeを！

# 参考文献

https://docs.unity3d.com/Packages/com.unity.dt.app-ui@1.0/manual/index.html

https://github.com/Cysharp/Claudia

https://qiita.com/kiiwami/items/4a62a3dcbedeb141e605

https://speakerdeck.com/andpad/fu-za-naapuriworedux-plus-mvvmdewan-bi-nizhi-yu-suru

https://redux.js.org/tutorials/essentials/part-1-overview-concepts#redux-application-data-flow

https://zenn.dev/takuty/articles/b12f4011871058#viewmodel%EF%BC%88%E3%83%90%E3%82%A4%E3%83%B3%E3%83%89%EF%BC%89

https://support.touchgfx.com/ja/docs/development/ui-development/software-architecture/model-view-presenter-design-pattern

https://light11.hatenadiary.com/entry/2020/05/23/194951