Unityエンジニアの大庭@ohbashunsukeです。
去年のUnityアドベントカレンダー2020でUnityの次世代UIシステムという位置づけのUI Toolkitについて執筆しました。
UI Toolkitを検証するモチベーション
僕は普段の業務でUI開発に携わっています。
基本はuGUIベースのPrefabワークフローでUIを作っていて知見は溜まってきました。
大抵の課題はuGUIで解決出来ると思っています。
一方Unityが公式で発表しているUIシステム「UI Toolkit」はHTML/CSSといったフロント技術からインスピレーションを受けた技術でuGUIとは全く違うアプローチです。
GameObjectをほぼほぼ使用しないUI開発というのはUI畑にいる者としては興味がそそられます。
マネージャー視点ではチームビルドによって開発手法を今までとは大きく変えることも必要で、そんな時のために開発手法の手札は多いに越したことはありません。
- 単純に新しいUIシステムが面白そう
- 開発手法の手札を増やしたい
この2点が僕にとってのモチベーションとなっています。
※ここからが本題です。
「はたしてUI Toolkitで多人数開発は出来るのか?」
という視点で検証していきたいと思います。
最初に注意点
実戦投入したポストモーテムではなく個人で検証した内容ですので、その点予めご了承ください。
またUI Toolkitはpreview版と絶賛開発中であり、今後仕様変更されるかも知れません。
対象読者
UI Toolkitを触ったことがあり、UI ToolkitでUI開発ワークフローを模索している方向けとなっております。
UI Toolkitにおける基本的な情報は割愛します。
※繰り返しになりますがコチラを参考にしてください
タイトルの通り多人数開発は可能なのか?という事に焦点を当てています。
目次
- UI Toolkitを検証するモチベーション
- 対象読者
- 目次
- 検証環境
- 今回作ってみたサンプル
- UXML/USSの構成
- テンプレート機能を使ったUXMLファイル分割
- アニメーション実装
- その他
- まとめ
- 結局実践投入出来るのか?
- 最後に余談
- 参考資料
検証環境
- Unity2020.2.0f1
- UI Toolkit 1.0.0-preview.13
今回作ってみたサンプル
ScreenA~Cの3画面をフッターメニューから切り替えるというシンプルなサンプルをUI Toolkitで作ってみました。
UXML/USSの構成
├── Uss │ ├── Common.uss ├── Uxml ├── SampleScreenManager.uxml ├── ScreenA.uxml ├── ScreenB.uxml ├── ScreenC.uxml ※一部省略
UXMLが4ファイル、共通のUSSが1ファイルという構成です。
Common.uss
は各UXMLから参照されています。
ところで「複数人が同時に作業できること」は多人数開発においては非常に重要です。
■ Prefabワークフローを振り返ります。
分割したPrefabを開発者が各々作業することで複数人の同時開発を実現できていると言えます。
また、NestedPrefabの登場で更に環境は向上しカスタマイズしやすくなっています。
■ UI Toolkitはどうでしょうか?
UXMLは今までのPrefabワークフローで言えば「Prefab」にあたります。
はたしてNestedPrefabに匹敵する分割能力を持っているのでしょうか?
テンプレート機能を使ったUXMLファイル分割
UXMLは分割して作業する事が可能です。
SampleScreenManager.uxml
を見ていきましょう。
今回の設計では、SampleScreenManager.uxmlは各画面の親に該当します。
<ui:UXML xmlns:ui="UnityEngine.UIElements" engine="UnityEngine.UIElements"> <ui:Template name="ScreenA" src="ScreenA.uxml" /> <ui:Template name="ScreenB" src="ScreenB.uxml" /> <ui:Template name="ScreenC" src="ScreenC.uxml" /> <Style src="/Assets/Sample/Uss/Common.uss" /> <SampleScreenManager class="screen"> <ui:Instance template="ScreenA" class="screen" /> <ui:Instance template="ScreenB" class="screen" /> <ui:Instance template="ScreenC" class="screen" /> <!-- 省略 --> </SampleScreenManager> </ui:UXML>
このような感じで、UXMLの中に外部のUXMLを追加することが出来ます。
■UXML : SampleScreenManagerの中に UXML : ScreenAを追加している箇所
<ui:Template name="ScreenA" src="ScreenA.uxml" />
テンプレート機能でUXMLを追加。
<ui:Instance template="ScreenA" class="screen" />
追加したUXMLのインスタンス化。
このようにUXMLを分割することが出来るため、各画面単位のUXMLを複数人でそれぞれ同時に開発するといったことが可能です。
またUXMLはただのXML形式のテキストファイルのため、Prefabと違いコンフリクトしたとしても致命的な障害にはなりません。
USSも同様に分割可能
<Style src="/Assets/Sample/Uss/Common.uss" />
先のソースコード内の上記の部分がUSS参照箇所になります。
CSSをHTMLに外部ファイルとして読み込む時と同じような感覚です。
- プロジェクト共通USS
- 各シーン共通USS
- 各画面単位固有USS
といったUSSの分割が想定されます。
UXMLに必要なUSSをそれぞれ参照をするため、同時開発は可能でしょう。
共通USS(Common.uss)は、同時に複数人が触ってしまうかも知れません。
こちらもUXMLと同様、USSはCSS形式のテキストファイルなので、コンフリクトしたとしてもたかが知れています。
この辺りはPrefabのコンフリクトより障壁が下がっていると考えられます。
VisualElementの拡張
UI ToolkitにおけるMonoBehaviourはVisualElementです。
MonoBehaviourを継承してコンポーネントを作っていくように、UI ToolkitもVisualElementを継承したクラスを作成して、作りたいUIを構築していくことになります。
// 画面のベースクラス public class ScreenBase : VisualElement { public new class UxmlFactory : UxmlFactory<ScreenBase, UxmlTraits> { } // 画面の識別Type public ScreenType ScreenType { get; set; } // 画面表示前の準備 public void Ready() { /*省略*/ } // 画面の表示 public async Task Show() { /*省略*/ } // 画面の非表示 public async Task Hide() { /*省略*/ } } // 画面Aクラス public class ScreenA : ScreenBase { public new class UxmlFactory : UxmlFactory<ScreenA, UxmlTraits> { } public ScreenA() { ScreenType = ScreenType.A; } }
このようにVisualElement
クラスを継承して必要なAPIを実装していきます。
ところで以下の見慣れない記述。
これはVisualElementを継承した際は必要になります。この1行が無いとVisualElementを拡張したものとして認識されません。
public new class UxmlFactory : UxmlFactory<ScreenBase, UxmlTraits> { }
この記述をすることで、UXML上に<ScreenA />
とVisualElement拡張後のクラスを書くことが出来ます。
親階層から子階層の要素の取得方法
UXML分割の話で使用したソースコード内の親子関係の話になります。
<SampleScreenManager class="screen">・・・・親階層 <ui:Instance template="ScreenA" class="screen" />・・・・子階層
SampleScreenManager
からScreenA
をどうやって取得するのか?という話です。
var screen = this.Q<ScreenA>("ScreenA"); await screen.Show();
親要素SampleScreenManager.cs
から子要素ScreenA
を呼ぶサンプルです。
このようにQメソッド
で型とnameを指定して取得できます。
var screen = this.Q<ScreenBase>("ScreenA"); Debug.Log(screen.ScreenType); // => 出力 : A
上記のように型の指定は親クラスでも可能です。
アニメーション実装
ここまでは画面構築の話でしたが、ここからはUIアニメーションについて言及していきます。
アドベントカレンダーに書きましたが、UI Toolkitのアニメーション作成方法は選択肢が限られます。
基本的にソースコードから操作する以外に手段がありません。
// 画面を表示するアニメーション DOTween.To(() => transform.position, x => transform.position = x, Vector3.zero, 0.6f) .SetEase(Ease.InOutQuart); // 画面を非表示にするアニメーション DOTween.To(() => transform.position, x=>transform.position = x, new Vector3(-ScreenWidth, 0, 0), 0.6f) .SetEase(Ease.InOutQuart);
DOTweenを使って、画面を表示/非表示時のスライドアニメーションを実装しています。
一応UI Toolkit側にもアニメーションライブラリがありますがDOTweenのシンプル版といった立ち位置で現状Experimentalリリースです。
参考 : Class ValueAnimation<T> | UI Toolkit | 1.0.0-preview.13
アニメーションの多人数開発はモノによっては厳しい
ボタンや画面遷移といった使い回す必要があり、ソースコードで実装したほうが良いと思われるものは問題なさそうです。
※UIアニメーションについては持論を展開していますのでコチラもどうぞ
ただしゲーム開発でよくあるガチャ演出
、強化演出
といった一点物で複雑になりやすいアニメーションを作るのは一気に難易度が上がります。
また非エンジニアにソースコードを書いてもらうのは、相当ハードルが高くほぼほぼ無理ゲーです。
こういった複雑なアニメーションはUI Toolkitを使わず、GameObjectで作ってしまった方が良いでしょう。
適切な技術選定が必要になりそうです。
その他
フッターメニューから画面遷移を行うような細かい処理はGithubに全ソースアップ済みですので、そちらをご覧いただければと思います。
まとめ
簡単な画面遷移を元にして、UI Toolkitが多人数開発に使えるのかを検証してきました。
基本的にはPrefabワークフローと同様、ファイルを分割することはできるため多人数開発は可能 と言えるでしょう。
- もう少しガッツリ作り込んだ画面遷移
- ダイアログ
- 通信処理
- アセットバンドルの利用
- シーン遷移
- 起動処理周り
- バトルなどのインゲーム実装
この辺りをUI Toolkitで作り込んでみないと自信は持てません。
ものすごい落とし穴があるかも知れません。
※何とかして作れるとは思いますが、uGUIワークフローより優れているかどうかは分からないという意味
■ 現状思いつくメリット
- Prefabと違っててUXML/USSはテキストなので修正差分が分かりやすく、ブラックボックスになりにくい
- テキストファイルなのでコンフリクトに強い
- UXMLにUI要素が全て書かれてあるので把握しやすい
- 今回言及していませんが、UXMLを作成するEditor拡張UI Builderが使いやすい
- USSを変える(テキスト修正のみ)だけでUIデザインを変更できる
■ 現状思いつくデメリット
- 実行中にコンポーネントの状態を可視化出来ない
- アニメーションはスクリプトオンリーで、AnimationClipは使えない
- ParticleSystemをUI Toolkitで挟むとか出来なそう(未検証)
- カスタムシェーダの適用方法が分からない
- uGUI開発にせっかく慣れてきたクリエーターがまた最初からワークフローを覚え直すこと
- (気づいていないだけでデメリットまだまだありそう)
結局実践投入出来るのか?
「現状分かりません」
まだまだ検証すべきことが多すぎて判断できない状態です。
今今プロジェクトが立ち上がる場合、開発期間にも依りますがuGUIで作る判断をすると思います。
※UI ToolkitはまだPreview版ですし
UI Toolkitは今後も開発されていく予定なので、ウォッチしてTwitter、ブログ、Qiitaあたりにアウトプットしていこうと思います。
最後に余談
Unity公式が提供するuGUIとUI Toolkitの比較表がありますので、興味ある方はコチラもどうぞ。
参考資料
- UI Toolkit | UI Toolkit | 1.0.0-preview.13
- UnityCsReference/External/MirroredPackageSources/com.unity.ui/Core/UXML at master · Unity-Technologies/UnityCsReference · GitHub
- GitHub - Unity-Technologies/UIToolkitUnityRoyaleRuntimeDemo: This is a sample project to introduce the use of UI Toolkit in Runtime