Unity UI ToolkitをRuntimeで導入してみたが、早計だったかもしれない

こんにちは。Sun\*でモバイルエンジニアをやっている@kukio828です。
この記事はSun\* Advent Calendar 2022の19日目の記事です。

弊社では今年、UnityプロジェクトでUI Toolkitを採用したことがありました。
が、結構いろいろなつらみがあり、結論、UITKのRuntimeでの導入はまだ早かったかもしれないと感じています。
UITKがどうこうというだけでなく、プロジェクトの進め方にも大いに反省点はあるのですが・・、今回は、振り返り含めそのことを書こうと思います。
UITKの使用を検討している方だけでなく、これから新しい技術を採用しようとしている方にも参考になれば幸いです！

## 前提
まず最初に、UITKそのものについてと、今回UITKを導入したプロジェクトについて簡単にご紹介します。

### UI Toolkitとは
- Unityの新UIシステム。登場時はEditor専用だったが、2022.2からはRuntimeもサポートされるようになった
- Webページのパラダイムにインスパイアされており、マークアップ言語でUIを組んでいくことができる。テンプレートファイルであるuxml（WebでいうHTMLに相当）とスタイルシートであるuss（Webでいうcssに相当）の二つのファイルをUIDocumentコンポーネントに渡すことでcanvas上に描画される。
- Unity公式としては、旧UIシステム（uGUI）を将来的にUITKに置き換えたい方針。今後新規に作成するプロジェクトではuGUIではなくてUITKを採用することを奨励している
- 詳しくは[公式ページ](https://unity.com/features/ui-toolkit#customize-ui-and-editor)参照

### 導入したプロジェクトについて
- iOS/Androidをターゲットとしたモバイルアプリ
- ノンゲームだが、アニメーションに物理演算を使いたい、将来的にVR化したい、などの要件がありUnityを採用
- ホワイトラベル型のビジネスモデル。まず基盤を開発して、ビジネスパートナーの特色に合わせてガワを変えたバリエーションを短期でどんどんリリースしていく想定。

## なぜUITKを採用したのか
当プロジェクトでは、以下の理由からUITKを採用するに至りました。
1. 実装方法がビジネスモデルとマッチしていた
1. ノンコードでUIが組めるツールが提供されていた
1. 公式で推奨されていた（ので、導入しても大丈夫だろうと思った）
以下、順番に詳細を書いていきます。

### 実装方法がビジネスモデルとマッチしていた
- 前述の通り、本プロジェクトはガワを変えたアプリをスピーディーに作っていくホワイトラベル型のビジネスモデルを想定
- 今回のビジネスモデルをuGUIで実現しようとした場合、ビジネスパートナーごとにPrefabを作ることになるが、UITKの場合はスクリプトさえ作っておけば、uxml/ussを差し替えるだけで要素を増減したり、見た目を変えたりすることができるため、UITKの方がマッチしていると判断
### ノンコードでUIが組めるツールが提供されていた
- UITKでは、UI BuilderというGUIツールが公式で提供されている
- GUIでリアルタイムのプレビューを見ながらUI要素を配置したりスタイリングができるツール。UI Builderで作成したUIはuxml/ussとして出力される。uGUIにはないUITKの強みの一つ
- 今回のプロジェクトでは、最終的には１バリエーション2週間程度のスパンで提供できることが理想とされていた。あらかじめUITKで作っておけば、非エンジニアでもこのツールを使ってUIがいじれるようになって、バリエーションの提供がスピーディーにできるのではないか、という期待があった
### 公式で推奨されていた（ので、導入しても大丈夫だろうと思った）
- （これは当時はっきりと言語化されていたわけではなく、後から振り返ってみて、ですが・・）
- UITKをあえて選んだ理由、というより、UITKを選ぶことを疑わなかった理由として、公式で推奨されていることは大きかった
- Sun\*社内でもUnityを採用した事例はまだ少なく、プロジェクトメンバーはUnity自体をまずキャッチアップする必要があった。今からuGUIを学ぶより最新技術であるUITKを使った方がいいだろう、という判断もあったと思う

## 実際にUITKで実装してみて・・
期待通り、UITKによって楽になったこともありました。が、それ以上につらみが多く、結果メリットにデメリットが勝ってしまい、「uGUIで作っておけばこんな苦労はしなかっただろうな・・」と思う場面が多くなってしまいました。以下に期待とのギャップと反省点を書いていきます。

### スタイルの変更を柔軟に行えそう -> できた
こちらは期待通りでした。uGUIでもPrefab Variantの機能を使ってUIの見た目にバリエーションをつけることは可能ですが、テンプレートファイルを差し替えるだけのUITKの方が、直感的で、Gitで差分も見やすかったです。また、uGUIにはない機能がいろいろ提供されており、こちらも便利でした。以下、今回特に便利だった機能をご紹介します。
- Theming機能
    - UITKでは、theme style sheet（tss)というテーマとして共通で使いたい値やスタイルが定義されているussをまとめたスタイルシートを作ることができる。このファイルをPanelSettingsという設定ファイルに適用すると、そのPanelSettingsを読み込んでいる全てのUI Documentにテーマが適用される。
    - テーマは親子関係にすることも出来、ベースのテーマを作っておき、一部をオーバーライドしたバリエーションテーマを作成する、ということも可能
- プロパティアニメーション
    - cssのtransitionプロパティに近い機能。ussクラスの付け外し時にopacity, position, scaleなど値をイーシングさせることができる。cssのanimationのようなループする動きはできないが、「チェックボックスがアクティブになった時」「ボタンが押された時」など状態遷移に伴うアニメーションに使える
    - プロパティアニメーションの定義はussに書くので、ussを差し替えるだけでアニメーションを切り替えることが可能

### 非エンジニアでもUIが組めそう -> できなかった
こちらは期待通りにはいきませんでした。原因は大きく二つあり、プロジェクトの進め方に問題があったのと、そもそもGUIツールというものに多くを求めすぎていたというのもあります。UITKどうこうというよりチームの問題が大きい。。
- プロジェクトの進め方の問題
    - 「非エンジニア」＝誰なのか、がフワッとしていた。「UITKを採用すれば非エンジニアでもUIが組めそう」というぼんやりとした構想はあったが、エンジニアでなければ誰がやるのか、そもそも自社でやるのか、ビジネスパートナー側にやってもらうのか、具体的なプランは決まっていなかった。実際に実装フェーズに入ったらデザインサイドにリソースの余裕がなく、結局、エンジニアチームでUIを組むことになった。
    - Hackのしすぎ。UITKにはButtonやListなどの要素がデフォルトで用意されているが、これをオーバーライドしてカスタム要素を作成することもできる。このカスタム機能を活用して、「データバインディングに対応させる」「UnityのLocalizationパッケージと連動させる」などして工数の削減を図ったところ、オーバーエンジニアリング気味になっていき、結果カスタム要素の使い方を知っているエンジニアしかUIが組めなくなってしまった。
- GUIツールに期待しすぎ
    - ローコード/ノーコードツール全般に言えることかもしれないが、ツールがあれば誰でもUIが組めるわけではなく、uxml/ussのキャッチアップは必要。flexboxや階層の組み方を理解していないと、GUIツール上では綺麗に組めたように見えてもレスポンシブなUIはできない
    - ツールから出力されたuxml/ussは冗長な記述が多く、手で書いたものと比べると汚い。差分の確認も大変
    - 結局UI BuilderでUIを組むことは早々になくなり、手でuxml/ussを書いてUI Builderでプレビューを見るという使い方になった

### 公式で推奨されているので、導入しても大丈夫だろう -> そうでもなかった・・
こちらも期待通りに行かなかったことです。一番ギャップがあり最も苦労した点でもあります。
- 情報が少ない
推奨されているとはいえまだまだuGUI人口の方が多く、特にRuntimeかつMobileで使っているチームは自分達くらいしかいないのではというくらいネット上に情報が少なかった。エラーや実装方法で行き詰まった時、検索してもほとんどの場合情報が得られないので、自力でコードを読み解くか、Unity Forumに投稿して返事を待つしかなかった。
- バグがある
使用者がまだ少ないせいか、Mobileで発生するバグがまだ結構（小さなものからアプリがクラッシュするレベルのものまで）あった。レポートを上げれば修正はしてもらえるが、レポートを上げるためにUnity側のバグなのかこちらの実装に問題があるのか切り分け調査をしなければならず、スケジュールを圧迫した。
- ベストプラクティスが確立されていないため、設計にスキルと工数が必要
これも使用者が少ないことに関連するが、実装やアーキテクチャのあるべきがまだ確立されていない。そのため、画面遷移の仕組みなどを１から考えて作る必要があった。今回はアーキテクトが画面遷移コンポーネントを作ることになったが、BEやインフラも兼任しており多忙だったため、他のメンバーのボトルネックになった。

### その他苦労した点
UITKの制約事項でも苦労したので、そのことについても書いておきます。
- Sprite Animationに非対応
UITKはSpriteは対応しているがSprite Animationは非対応。UITKで作ったUIはすべてのGameObjectの上にオーバーレイされるので、UIの上にSprite Rendererを配置してAnimationを再生させるようなことも出来ない。そのため、「UIの裏でSprite Animationを再生し、それをRender Textureに出力し、UIのバックグランド画像としてRender Textureを指定する」という非常に泥臭いワークアラウンドをする必要があった。
- アセットやライブラリの多くがUITK非対応
自前実装での対応が必要になる。特に辛かったのは以下の対応。
    - 絵文字対応
UITKは内部的にTextMeshProを使っているので、SpriteAssetsでUnicodeと絵文字の紐付けを行えば、絵文字を表示することは可能だが、この方法は合成絵文字は表示できず、また入力にも対応していない。uGUIでTMPを使っても同じ制約があるが、サードパーティ製のAPI（[Full Support Emoji API](https://forum.unity.com/threads/full-emoji-support-api-emoji-sequen.660310/#post-4420162))があるのでこれを入れれば簡単に対応できる。Full Support Emoji APIはUITKは対応していないので、UITK用の対応を自前実装する必要があった
    - 文字入力のUX改善
キーボードで入力欄が隠れる、テキストプレビューが隠せない、など、標準のTextInputをそのまま使うと入力に関するストレスが多かった。これも、uGUIだったらサードパーティ製のAPIがあるが以下略


## 反省と教訓
色んな意味でUITK採用は「早計だった」のですが、では何が早かったのか、どうなってから使うべきだったのかのでしょうか。以下に自戒含めて書きます。
- もっと普及してから使うべきだった
    - Unityは「アセットストアが充実している」「コミュニティが活発」というのが大きな強みだが、UITKのような最新技術を使うとこの恩恵が得られないのがめちゃくちゃ痛い
    - 公式で推奨されていたとしても、自分と同じような条件でその技術を採用している前例がない場合は警戒した方がいい。Unityはクロスプラットフォームなので、同じ環境で使った人がいなければ、まだ発見されていないバグを自分で踏む可能性がある。
    - そもそもUnity界隈では最新技術を積極的に取り入れるのではなく、枯れたStableを使うのが定石？らしい（どの動画だったかは控えていないのですが、海外のインディゲームデベロッパの方がYouTubeでそんなことを語っているのを見かけて、なるほどなと思ったことがありました。実際はそんなことないよ、というご指摘あればコメントいただきたいです）
- まずは比較的規模の小さいプロジェクトで試すべきだった
    - 今回の案件は基盤開発だったので、設計の難易度も比較的高く、チームメンバーも多かった。この規模感で正解のわからない新技術を採用すると、誰もリードができない
    - UITKを使うにしても、まずはPOCなどの比較的小さめの案件で誰かが試して、前例を作った上で採用するべきだった
- Hackはもっと慣れてからするべきだった
    - 今回UITKが使いづらくなってしまった大きな原因として、「カスタム要素を作り込みすぎたこと」「画面遷移コンポーネントを自前で作ったこと」は大きかった
    - 再利用性の向上や効率を期待してこれらのHackを行ったが、結果想定外の動きをしてバグになったり、実装者以外が使いこなせなくてボトルネックになったりなどむしろ効率が下がった
    - 新しい技術を使う時点である程度の不便さは覚悟するべき。全容が見えていない状態でこれもっと効率的にできるんじゃないか、とHack欲が沸いたとしても、グッと堪えてまずは公式に推奨されている通りの方法で一通り実装してみるべきだった

## おわりに
ここまでいろいろ書きましたが、UITKのパラダイム自体は筆者も好きで、uGUIと比較してかなり進化した使いやすいUIシステムであるということは実装していてかなり感じました。早くUnity標準のUIシステムはUITKです、という状態になってほしいなと筆者は思っています。まあでもとにかくアセットが使えないのが辛いので、大手アセットたちが対応してくれるまではRuntimeで使うことはないかなー・・

----
[Sun* Advent Calender](https://adventar.org/calendars/8211)はクリスマスまでほぼ毎日記事を更新しています！
明日の記事は弊社デザイナーである早川さんの「休日アウトプットのすゝめ」です。お楽しみに！