Unity UI の次のステップへ
Unity の従来の UI システム(uGUI / Canvas)は長年使われてきましたが、パフォーマンスの課題や CSS ライクなスタイリングの欠如といった制限があります。UI Toolkit は Unity が推進する次世代の UI フレームワークで、Web 技術(HTML/CSS)に近い設計思想を持っています。
Antigravity の AI エージェントは、UI Toolkit の UXML(レイアウト)と USS(スタイル)を自然言語から生成でき、Web 開発の経験がそのまま活かせるワークフローを提供します。
UI Toolkit の基本構造
UI Toolkit は3つの要素で構成されます:
- UXML: HTML に相当するレイアウト定義(
.uxmlファイル) - USS: CSS に相当するスタイル定義(
.ussファイル) - C# コントローラー: ロジックとデータバインディング
UXML (レイアウト) ←→ USS (スタイル)
↑
C# コントローラー
Antigravity でのセットアップ
プロジェクト構造の生成
Antigravity への指示:
Unity UI Toolkit プロジェクトのフォルダ構造を作成してください。
構成:
Assets/
UI/
Layouts/ ← UXML ファイル
Styles/ ← USS ファイル
Scripts/ ← C# コントローラー
Resources/ ← アイコン・フォント
ゲームの種類: RPG
必要な画面: タイトル、メインメニュー、インベントリ、ステータス、
ダイアログ、設定、バトル HUD
Antigravity はフォルダ構造と各画面の UXML/USS/C# ファイルの雛形を一括生成します。
UXML レイアウトの自動生成
インベントリ画面の例
Antigravity への指示:
RPG のインベントリ画面を UI Toolkit で作成してください。
レイアウト:
- 左パネル: アイテムリスト(スクロール可能、アイコン+名前+数量)
- 右パネル: 選択アイテムの詳細(画像、説明、ステータス効果)
- 下部: 「使う」「捨てる」「装備」ボタン
- カテゴリタブ: 全て / 武器 / 防具 / 消耗品 / 素材
スタイル: ダークファンタジー風、半透明背景
Antigravity が生成する UXML:
<?xml version="1.0" encoding="utf-8"?>
<ui:UXML xmlns:ui="UnityEngine.UIElements"
xmlns:uie="UnityEditor.UIElements">
<ui:VisualElement name="inventory-root" class="inventory-panel">
<!-- カテゴリタブ -->
<ui:VisualElement name="category-tabs" class="tab-bar">
<ui:Button name="tab-all" text="ALL" class="tab-button active"/>
<ui:Button name="tab-weapon" text="WEAPON" class="tab-button"/>
<ui:Button name="tab-armor" text="ARMOR" class="tab-button"/>
<ui:Button name="tab-consumable" text="ITEM" class="tab-button"/>
<ui:Button name="tab-material" text="MATERIAL" class="tab-button"/>
</ui:VisualElement>
<ui:VisualElement name="content-area" class="content-row">
<!-- 左パネル: アイテムリスト -->
<ui:ScrollView name="item-list" class="item-list-panel">
<ui:VisualElement name="item-list-container"/>
</ui:ScrollView>
<!-- 右パネル: アイテム詳細 -->
<ui:VisualElement name="item-detail" class="detail-panel">
<ui:VisualElement name="item-icon-large" class="detail-icon"/>
<ui:Label name="item-name" text="Select an item" class="detail-name"/>
<ui:Label name="item-description" class="detail-desc"/>
<ui:VisualElement name="stat-effects" class="stat-container"/>
</ui:VisualElement>
</ui:VisualElement>
<!-- 下部アクションボタン -->
<ui:VisualElement name="action-bar" class="action-bar">
<ui:Button name="btn-use" text="USE" class="action-button primary"/>
<ui:Button name="btn-equip" text="EQUIP" class="action-button"/>
<ui:Button name="btn-discard" text="DISCARD" class="action-button danger"/>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>USS スタイリングの自動生成
ダークファンタジーテーマ
上記のインベントリ画面用の USS を作成してください。
テーマ: ダークファンタジー
- 背景: 半透明の暗い紫(#1a0a2e, 90%)
- アクセント: ゴールド(#c9a84c)
- テキスト: 明るいグレー(#e0d8cc)
- ボタン: ゴールドのボーダー、ホバーで輝く
- フォント: 中世風を想定(Unity のデフォルトフォント使用)
- アニメーション: ホバー時にスケール変化
Antigravity が生成する USS:
/* インベントリパネル全体 */
.inventory-panel {
width: 100%;
height: 100%;
background-color: rgba(26, 10, 46, 0.92);
padding: 16px;
flex-direction: column;
}
/* カテゴリタブ */
.tab-bar {
flex-direction: row;
height: 48px;
margin-bottom: 12px;
border-bottom-width: 2px;
border-bottom-color: rgba(201, 168, 76, 0.3);
}
.tab-button {
flex-grow: 1;
background-color: transparent;
color: #8a7e6e;
font-size: 14px;
border-width: 0;
border-bottom-width: 3px;
border-bottom-color: transparent;
-unity-font-style: bold;
transition-duration: 0.2s;
}
.tab-button:hover {
color: #c9a84c;
background-color: rgba(201, 168, 76, 0.08);
}
.tab-button.active {
color: #c9a84c;
border-bottom-color: #c9a84c;
}
/* コンテンツエリア */
.content-row {
flex-direction: row;
flex-grow: 1;
}
/* アイテムリスト */
.item-list-panel {
width: 55%;
margin-right: 12px;
}
.item-entry {
flex-direction: row;
align-items: center;
padding: 8px 12px;
margin-bottom: 4px;
background-color: rgba(255, 255, 255, 0.03);
border-radius: 6px;
transition-duration: 0.15s;
}
.item-entry:hover {
background-color: rgba(201, 168, 76, 0.12);
scale: 1.01;
}
.item-entry.selected {
background-color: rgba(201, 168, 76, 0.18);
border-width: 1px;
border-color: #c9a84c;
}
/* 詳細パネル */
.detail-panel {
width: 45%;
background-color: rgba(0, 0, 0, 0.25);
border-radius: 8px;
padding: 20px;
align-items: center;
}
.detail-icon {
width: 128px;
height: 128px;
border-width: 2px;
border-color: #c9a84c;
border-radius: 12px;
margin-bottom: 16px;
}
.detail-name {
font-size: 22px;
color: #c9a84c;
-unity-font-style: bold;
margin-bottom: 8px;
}
.detail-desc {
font-size: 14px;
color: #b0a898;
white-space: normal;
margin-bottom: 16px;
}
/* アクションボタン */
.action-bar {
flex-direction: row;
height: 50px;
margin-top: 12px;
justify-content: center;
}
.action-button {
min-width: 120px;
height: 42px;
margin: 0 8px;
background-color: rgba(201, 168, 76, 0.15);
border-width: 1px;
border-color: #c9a84c;
border-radius: 6px;
color: #e0d8cc;
font-size: 15px;
-unity-font-style: bold;
transition-duration: 0.2s;
}
.action-button:hover {
background-color: rgba(201, 168, 76, 0.3);
scale: 1.04;
}
.action-button.primary {
background-color: rgba(201, 168, 76, 0.35);
}
.action-button.danger {
border-color: #8b3a3a;
color: #c47070;
}C# コントローラーの生成
上記のインベントリ画面の C# コントローラーを作成してください。
要件:
- ScriptableObject ベースのアイテムデータ
- ListView でアイテム一覧を表示(仮想化対応)
- アイテム選択で詳細パネル更新
- カテゴリフィルター機能
- ボタンイベントのバインディング
Antigravity が生成する C#:
using UnityEngine;
using UnityEngine.UIElements;
using System.Collections.Generic;
using System.Linq;
public class InventoryController : MonoBehaviour
{
[SerializeField] private UIDocument uiDocument;
[SerializeField] private List<ItemData> allItems;
private ListView itemListView;
private VisualElement detailPanel;
private Label itemName, itemDescription;
private string activeCategory = "all";
private void OnEnable()
{
var root = uiDocument.rootVisualElement;
// UI 要素の参照を取得
itemListView = root.Q<ListView>("item-list-container") ??
CreateListView(root.Q<ScrollView>("item-list"));
detailPanel = root.Q("item-detail");
itemName = root.Q<Label>("item-name");
itemDescription = root.Q<Label>("item-description");
// カテゴリタブのイベント
BindCategoryTabs(root);
// アクションボタン
root.Q<Button>("btn-use")?.RegisterCallback<ClickEvent>(_ => UseItem());
root.Q<Button>("btn-equip")?.RegisterCallback<ClickEvent>(_ => EquipItem());
root.Q<Button>("btn-discard")?.RegisterCallback<ClickEvent>(_ => DiscardItem());
// 初期表示
RefreshItemList();
}
private void BindCategoryTabs(VisualElement root)
{
var tabs = new[] { "all", "weapon", "armor", "consumable", "material" };
foreach (var cat in tabs)
{
var btn = root.Q<Button>($"tab-{cat}");
btn?.RegisterCallback<ClickEvent>(_ =>
{
activeCategory = cat;
// タブの active クラスを切り替え
root.Query<Button>(className: "tab-button")
.ForEach(b => b.RemoveFromClassList("active"));
btn.AddToClassList("active");
RefreshItemList();
});
}
}
private void RefreshItemList()
{
var filtered = activeCategory == "all"
? allItems
: allItems.Where(i => i.category == activeCategory).ToList();
// ListView を更新(仮想化により大量アイテムでも高速)
// 実装は makeItem / bindItem パターンで構築
}
private void SelectItem(ItemData item)
{
itemName.text = item.displayName;
itemDescription.text = item.description;
// 詳細パネルを更新...
}
private void UseItem() { /* 使用ロジック */ }
private void EquipItem() { /* 装備ロジック */ }
private void DiscardItem() { /* 破棄ロジック */ }
}Canvas(uGUI)からの移行
既存の Canvas ベースの UI を UI Toolkit に移行する場合も、Antigravity が支援します。
以下の Canvas (uGUI) ベースの UI コードを
UI Toolkit (UXML + USS + C#) に移行してください。
[既存の Canvas UI コードを貼り付け]
移行の方針:
- RectTransform → USS flexbox レイアウト
- Image コンポーネント → VisualElement + background-image
- Text (TMP) → Label
- Button → ui:Button
- ScrollRect → ui:ScrollView
- 全アニメーションを USS transition に変換
パフォーマンス: Canvas vs UI Toolkit
| 項目 | Canvas (uGUI) | UI Toolkit |
|---|---|---|
| 再描画コスト | Canvas 全体を再構築 | 変更要素のみ更新 |
| バッチング | 手動で Canvas 分割が必要 | 自動で効率的にバッチ |
| 仮想化リスト | なし(全要素を生成) | ListView で仮想化対応 |
| スタイル管理 | インスペクターで個別設定 | USS で一元管理 |
| メモリ使用量 | GameObject ベースで重い | 軽量な VisualElement |
特にアイテムが 100 件を超えるリストでは、UI Toolkit の ListView(仮想化)が Canvas の ScrollRect より明確に軽量です。
全体を振り返って
Unity UI Toolkit と Antigravity の組み合わせは、UI 開発を大幅に効率化します。
- UXML 自動生成: 画面仕様を自然言語で伝えるだけ
- USS スタイリング: テーマを言葉で指定、CSS ライクな記述を AI が生成
- C# コントローラー: データバインディングとイベント処理を自動実装
- Canvas からの移行: 既存 UI の変換を AI がサポート
UI Toolkit はまだ採用事例が少ない分、早期に導入することで先行者利益が得られます。Antigravity を使えば、学習コストを最小限に抑えながら最新の UI フレームワークを実プロジェクトに適用できます。
個人開発12年の現場で実感したこと
線引きするときの3つの判断軸
- 失敗時の影響が金銭やユーザー体験にどれだけ波及するか
- 復旧オペレーションが明文化されているか
- 観測ログから人間が再現できる粒度に整っているか