GGua 日本語リファレンス
英語版が正式な参照です。内容に差異がある場合は、英語版を優先してください。
UNITY / UI

導入とUI実装

GuaのUnityパッケージを追加すると、ランタイムが自動起動し、UI Toolkit、uGUI、TextMeshProの実行時UIを収集します。

1. UPMパッケージを追加する

  1. 最新GuaのReleaseを開く

    AssetsからUnity用.tgzをダウンロードします。

  2. Package Managerへ追加

    + → Add package from tarballを選択して、ダウンロードしたファイルを指定します。

  3. サンプルを取り込む

    Package ManagerのGua詳細画面でSamplesを開き、Runtime UI FixtureをImportすると、対応UIをまとめたシーンを確認できます。

2. 自動起動の仕組みを理解する

Godot版ではゲーム側がattach()とupdate()を呼びますが、Unity版ではUPMパッケージが同じ責務を自動で引き受けます。sceneごとにGua初期化scriptを追加する必要はありません。

BeforeSceneLoad→Runtime / Driverを生成→LateUpdate→UI収集・action配送
内部処理利用者から見た意味
GuaUnityRuntime.EnsureStarted()scene読込前にruntimeとWebSocket bridgeを一度だけ作ります。
GuaUnityBootstrap.LateUpdate()通常のUpdate()後に、そのframeのUI状態を収集します。
BeginFrame → collect → EndFrameUI Toolkit、uGUI、TMPを一つの整合したSemantic UI Treeとして公開します。
action配送外部requestをUnity Controlのevent/value変更へ適用し、request ID付き結果を返します。

3. UI Toolkitで実装する

BeforeSceneLoadでbootstrap driverとruntimeの2つの非表示・永続GameObjectが作られます。driverのLateUpdate()がruntimeのframe処理を進めます。利用者による初期化、semantic node登録、毎フレーム呼び出し、破棄処理は不要です。

UIDocument以下へ標準Controlを配置します。nameまたはviewDataKeyがGuaの安定IDとして使われます。

TitleScreen.uxmlxml
<ui:UXML xmlns:ui="UnityEngine.UIElements">
  <ui:Button name="start" text="Start Game" />
</ui:UXML>

UXMLの各記述

記述意味
<ui:UXML xmlns:ui="UnityEngine.UIElements">UI Toolkit標準elementを使うUXML documentのルートです。
<ui:Button name="start" text="Start Game" />表示textがStart GameのButtonを作り、name=startをGuaの安定ID候補にします。
UI Toolkitの短縮例csharp
using UnityEngine;
using UnityEngine.UIElements;

public sealed class TitleScreen : MonoBehaviour
{
    [SerializeField] private UIDocument document;

    private void OnEnable()
    {
        var root = document.rootVisualElement;
        var start = root.Q<Button>("start");
        start.clicked += () => Debug.Log("Start Game");
    }
}

UI Toolkit scriptを上から読む

記述意味
using UnityEngine.UIElements;UIDocument、VisualElement、ButtonなどUI Toolkit型を読み込みます。
public sealed class TitleScreen : MonoBehaviourscene上のGameObjectへ付ける通常のgame scriptです。Gua専用base classではありません。
[SerializeField] private UIDocument document;Inspectorから、このscriptが操作するUIDocumentを割り当てます。
private void OnEnable()GameObjectが有効になった時点でButton listenerを登録します。
var root = document.rootVisualElement;UIDocumentが生成したVisualElement treeのルートを取得します。
root.Q<Button>("start")UXMLのname=startを持つButtonを検索します。このnameはGuaのnode IDにも使われます。
start.clicked += ...通常のUnity click listenerです。Guaの外部clickもこのevent経路を通るため、test専用分岐は不要です。

上の例ではUXML側のButtonへname="start"を設定します。Button、Toggle、TextField、Slider、DropdownField、ListViewなどは自動的にSemantic UI Treeへ反映されます。

4. uGUI / TextMeshProで実装する

Canvas以下へ標準uGUI Controlを配置します。長期間テストから参照するGameObjectにはGuaIdを追加してIDを固定します。

uGUIの短縮例csharp
using Gua.Unity;
using UnityEngine;
using UnityEngine.UI;

public sealed class TitleScreen : MonoBehaviour
{
    [SerializeField] private Button startButton;

    private void Awake()
    {
        var id = startButton.GetComponent<GuaId>()
            ?? startButton.gameObject.AddComponent<GuaId>();
        id.Value = "start";
        startButton.onClick.AddListener(() => Debug.Log("Start Game"));
    }
}

uGUI scriptを上から読む

記述意味
using Gua.Unity;任意の安定IDを付けるGuaIdなどUnity向け公開型を読み込みます。
[SerializeField] private Button startButton;Canvas上のuGUI ButtonをInspectorから割り当てます。
private void Awake()listenerやIDを、最初のGua frameが収集される前に準備します。
startButton.GetComponent<GuaId>()既にGuaIdが付いていれば再利用します。
?? startButton.gameObject.AddComponent<GuaId>()無い場合だけGuaIdを追加し、componentの重複を避けます。
id.Value = "start"scene階層変更に影響されない固定node IDを設定します。
startButton.onClick.AddListener(...)通常のuGUI listenerを登録します。Gua clickもこのlistenerを発火させます。

TextMeshProのButton、InputField、Dropdown、Textも同じCanvas階層から収集されます。サンプル全体はGuaRuntimeUiSample.csとGuaUnityFixture.csで確認できます。

5. 安定IDと画面名を付ける

IDは自動生成されますが、テストから長期間参照する要素にはGuaIdを付けます。UI ToolkitはviewDataKey、次にnameを優先します。uGUI/TMPはGuaId.Valueが無ければscene path、Transform名、sibling indexから生成します。

任意の明示IDと論理画面csharp
using Gua.Unity;

startButton.gameObject.AddComponent<GuaId>().Value = "start";
screenRoot.AddComponent<GuaScreen>().Value = "title";

IDと画面名の意味

記述意味
using Gua.Unity;GuaIdとGuaScreen componentを参照できるようにします。
AddComponent<GuaId>().Value = "start"ButtonのGameObjectを外部testからstartという固定IDで参照できるようにします。既存componentがある場合はGetComponentで再利用してください。
AddComponent<GuaScreen>().Value = "title"現在の論理画面名をtitleとして公開します。画面単位のroot GameObjectへ一つだけ付けます。

6. World Object Treeを公開する

UIではないdoor、enemy、objectiveなどを公開する場合は、対象のGameObjectへGuaWorldObject componentを追加します。UPM runtimeが毎frame自動収集するため、sceneごとの登録loopは不要です。

Doorをゲーム世界のobjectとして公開csharp
using Gua.Core;
using Gua.Unity;
using UnityEngine;

public sealed class ReactorDoor : MonoBehaviour
{
    private GuaWorldObject worldObject;
    private bool locked = true;

    private void Awake()
    {
        worldObject = GetComponent<GuaWorldObject>()
            ?? gameObject.AddComponent<GuaWorldObject>();
        worldObject.Id = "reactor-door";
        worldObject.Kind = "door";
        worldObject.Label = "Reactor door";
        worldObject.Space = GuaWorldSpace.World3D;
        worldObject.VisibleToPlayer = true;
        worldObject.Tags = new[] { "reactor", "mission-critical" };
        PublishState();
    }

    public void SetLocked(bool value)
    {
        locked = value;
        PublishState();
    }

    private void PublishState()
    {
        worldObject.SetState("locked", locked);
        worldObject.SetState("power", "online");
    }
}

Idは必須かつ同じframe内で一意です。位置はGameObjectのtransform.positionから取得され、公開済みの親GameObjectがあれば最も近いobjectがparentになります。ID、kind、visibility、tagsなどのserialized fieldはInspector上のGuaWorldObject componentからも設定できます。動的なstateはコードからSetState()を呼び、string、number、boolean、nullだけを渡します。概念と検索方法はWorld Object Tree編を参照してください。

7. 外部接続を許可する

既定のWebSocketポートは8765です。プロセス起動前にGUA_BRIDGE_PORTを設定すると変更できます。Inspectorとgui-mcpはGodot版と同じブリッジへ接続します。

WebGLへExportする(実験的)

ReleaseのUPMパッケージにはWebGL native libraryとGuaWebMcp.jslibが含まれます。WebGL buildがtab-localな__guaUnityWebPortを導入するまで待ち、同じpageでgua-webmcpの引数なしのcreateUnityWebGlBridge()を呼びます。helperが既定のglobal名を解決します。この経路は常にPlayer投影を使い、privateなDebug dataを公開しません。

観測と操作の原則

  • 非表示nodeは消去せず、visible: falseとして観測します。無効状態もenabledへ反映します。
  • boundsはスクリーンショットと同じ物理pixel座標です。原点は左上、Xは右、Yは下です。
  • クリック、focus、値変更、選択、scroll、キー入力はUnityのControlへ適用され、request ID付きのaction結果が返ります。
  • 画面キャプチャはrendered Player/Play Modeで利用できます。batchmodeまたは-nographicsではheadlessを返します。

UI/Worldに追加の観測値を公開する

標準のtreeにない型付きの値はObserveで明示的に登録します。公開済みUI/World ownerに結び付け、オブジェクトの削除時に登録を解除します。ゲーム側のmanaged runtimeのCreateObserveOwnerから登録できます。Playerへの公開は明示的なopt-inです。エンジンごとの登録例とValue・登録・外部購読の説明を参照してください。