UDN
Search public documentation:

UserInterfaceOverviewJP
中国翻译
한국어

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

ユーザー インターフェース システム概観

ドキュメント概要: UI システム デザインと機能の概観。

ドキュメントの変更ログ: Ron Prestenback? により作成、Richard Nalezynski? により管理。

概観

このドキュメントは UI システムの主な機能を説明するものです。UI システムのデザインは、UI システム自体と UI エディタの 2 つの部分に分かれています。このデザインの実装は 3 つの段階で述べられ、詳しくは UserInterfaceImplementationJP? で説明されています。

UI システム

UI はアーティスト ドリブンのシステムであり、そこでアーティストは UI コントロールのレイアウトを作成し、それらのコントロールをゲーム データにバインドし、そのデータにさまざまなオペレーションを実行するため、Kismet を介してスクリプトされたイベントやアクションを作成します。UI システムはデータ ソース、プレゼンテーション、インタラクションの 3 つの主要なコンポーネントで構成されています。データ ソース コンポーネントは、UI がゲーム データとどのようにかかわるかを表し、プレゼンテーション コンポーネントは、UI がユーザーにどのようにしてデータを表示するかを表し、インタラクション コンポーネントは、UI システムがどのようにイベントをプロセス (ユーザーにより生成されるイベントとシステムにより生成されるイベントの両方) するかを表します。これら 3 つのコンポーネントは、以下でより詳細に説明されます。

データ ストア

データ ストアは、UI がどのようにしてゲームからデータを取り出し、ゲームへのデータの変更を公開するかを表します。データ ストアは永続性の場合があり、その場合は UI コントローラ オブジェクトにレジスタされ、付属となりすべてのウィジェットにより利用可能となります。一時性の場合もあり、この場合はその時点のシーンに付属となり、そのシーンに含まれるウィジェットのみからアクセスを受けることができます。データ ストアのデータのバインドと取り出しのインターフェースが同じでも、データ ストアが提供するデータのタイプに関わらず、UI にいかなるタイプのデータをも提供できます。

永続性のデータ ストアは、ゲームタイプ、キャラクター リソース、状態データなどの情報をトラックできますが、シーンごとのデータ ストアは、シーン内のウィジェットに入力された値や未決の接続状態の情報などをトラックできます。データ ストアは、すべてのゲームタイプの名前、キャラクター リソース データなどの静的情報を提供するだけでなく、その時点のゲームタイプの名前などの動的情報も提供することができます。

UI に使用されるデータ ストアには、いくつかの特別なタイプのものもあります。アクティブな UISkin は、そのシーンで利用可能なスタイルのリストを含み、'Styles' タグを使用することにより、ウィジェットにより参照することが可能です。'Attributes (属性)' データ ストアは、バーチャル データ ストアで UIString のテキスト スタイルを変更 (ボールド、イタリックなど) します。

データ ストアの機能

  • ウィジェットにデータを提供し、ウィジェットからのデータの変更を認識し、必要な場合そのデータを適切な場所にプロパゲートする。
  • クラスに基づいたデザインを通して、任意のデータ タイプにアクセスすることが可能。
  • 例えば、変更が起きるとすぐにそれをゲーム状態値に伝えるなどのように、根底にあるデータ ソースとリアルタイムのやり取りが可能。
  • データへの変更を公開する際に、遅れた、バッファされた、またはバッチされたトランザクションが可能。

データ ストアのカテゴリ

データ ストアには 4 つの主要なカテゴリがあります。

  1. ゲーム状態 – プレイヤー、目的、残り時間、その時点のスコアなど、その時点のゲーム状態に関するすべてのデータをトラックします。GameState データ ストアが、他のゲーム状態データ ストアへの参照を含むという意味で、ゲーム データ ストアはネスト化され得ると言えます。例えば、これは特定のプレイヤーに関わる武器のデータ ストアを隔離するのに便利です。ゲーム データ ストアは、以下の 2 つのコンポーネントに分かれています。
    • ゲーム状態データ プロバイダ: プレイヤー、武器、拾ったアイテム、ゲームの目的などのデータ ソースの特定のインスタンスに関する状態と静的データを提供します。データ プロバイダは、通常 UI により直接参照されません。その代わり、所有しているプレイヤー、またはその時点でのゲーム情報インスタンスに関わるゲーム状態データ ストアとして、ゲーム状態データ ストアを通してアクセスされます。
    • ゲーム状態データ ストア: ゲームと UI の間の第一の層として働きます。それぞれのデータ ストアは、ゲーム オブジェクトのインスタンスにデータを提供するような、ゲーム状態データ プロバイダの集合を含んでいます。
  2. ゲーム設定 – UI にゲーム固有、またはグローバルで構成可能な設定へのアクセスを提供します。ゲーム設定データ ストアは、ゲームタイプの設定された MaxPlayers、GoalScore などのデータとして、またはユーザーの設定したボタンのレイアウトなどのユーザー固有のデータとして公開することができます。ゲーム設定データ ストアは、ユーザーの選択を適切な永続性の場所に公開し、ゲームがプレイされると、これらの値がゲームプレイ コードにより使用されるようにします。
  3. 遠隔データ – ネットワークを通して遠隔マシンから受け取ったデータへのアクセスを UI に提供します。このタイプのデータ ストアの使用法の 1 つは、インターネット ゲーム セッションに関するゲームとプレイヤー データがマスター サーバーから取り出されるようなサーバー ブラウザとしてです。
  4. ゲーム リソース – ゲーム モード、武器の選択、キャラクターの選択、マップなどのゲーム内で利用可能なリソースに関するすべての情報をトラックします。

データ ストアの参照

各データ ストアには、UI がそのデータ ストアを認識できるような固有のタグがあります。データ ストア タグが実際のデータ ストアとどのように関連付けられているかの詳細は、一般的に必要性やデータ ストアのタイプの目的によって決定されます。データ値を UI に公開するために、各データ ストアはウィジェットにバインドされ得るプロパティに対応する名前のリストを提供します。

データ ストアやそれらの値は、マークアップ構文を使用して UI により参照されます。この構文は <DataStoreName:PropertyName> です。例えば、ゲームがユーザーに 3 つのコントローラ レイアウトの選択肢を提供し、現在のレイアウトの名前をコンフィギュレーション画面内のラベルに表示させたいと仮定しましょう。この設定をコントロールするプロパティにラベルをバインドするには、ラベルの値を <Controls:LayoutType> のようなものに設定します (この値をトラックをつかさどるデータ ストアがタグ 'Controls' を使用し、それがどのゲームパッド レイアウトを使用するかをコントロールする 'LayoutType' という名前のプロパティを公開すると仮定します)。

データ ストアは生存期間管理をカプセル化して、ガーベジ コレクションと繋がったデータ ストアにより表わされる根底にあるデータとウィジェットの間の参照が決してないようにするので、ウィジェットをバインドするこの方法は、UI がゲーム データを安全に参照できるようにします。

インタラクション

それぞれのウィジェットには、そのウィジェットに利用可能なイベントのリストを提供するような EventProvider コンポーネントが含まれています。EventComponents は、イベント クラスの配列 (実際にはこれらは Kismet システムの SequenceEvent クラスの子ですが、UIEvent と呼ばれます) を含みます。EventComponent に含まれるそれぞれの UIEvent インスタンスは、イベントがトリガされた際に実行されるアクションの集まりを持っています。特定のイベントに割り当てされたアクションのリストは、そのイベントを実装する各ウィジェットにとって異なります。

入力イベント (単純にするためにこれを UIEvent_ProcessInput と呼びます) を処理するのに特別な UIEvent クラスがあります。ウィジェットが入力をプロセスするには、その EventComponent がイベントのリストの中に UIEvent_ProcessInput を含んでいなければいけません。ビルトイン セットのウィジェットに関しては、入力を処理するべきすべてのウィジェットは、既にイベントのリストの中に入力プロセッサを持っています。デザイナーが (prefab を介して) 作成するカスタム ウィジェットに関しては、そのウィジェットに入力をプロセスさせたい場合、そのウィジェットにイベント プロセッサを追加することができます。UIEvent_ProcessInput クラスは、任意の数の入力キー イベントを処理することができます。処理される各入力イベントに関して、その入力の結果起こるべき 1 つ以上のアクションを定義することができます。従って、与えられたシーンで、入力プロセッサを含むウィジェットのみが、入力を処理できます。

イベント プロセッサを見ることで、ウィジェットがどの入力イベントを処理するかを決定できるので、どの時点でも、どのウィジェットがどの入力キー イベントに応答するかを決定し、そのシーンの他のすべてのウィジェットを無視することができます。入力をプロセスできるようなウィジェットのセットを変更してしまうようなイベントが起こると、シーンのポーリング可能なウィジェットのリストがアップデートされます。これは、入力キー名をウィジェットの配列にマップするようなストラクチャである InputEventSubscription を使用してカプセル化されます。InputEventSubscription に含まれるウィジェットは、その時点で入力をプロセスする資格のあるウィジェットで、EventComponent のリストの (その入力キーに応答するような) イベント内に UIEvent_ProcessInput イベントを含みます。典型的にウィジェットは、フォーカス チェーンの部分となっている場合にのみ、入力をプロセスする資格がありますが、非フォーカスの入力を認識するように設定されているウィジェットもまた、資格があるとみなされます。各シーンは InputEventSubscriptions への入力キー名のマッピングを持ちます。入力イベントを受信すると、シーンはそのキー名に対応する InputEventSubscription 構造体を取り出します。これで、その入力イベントを潜在的にプロセスできるようなすべてのウィジェットに、シーンが即時にアクセスできます。配列内でどの資格があるウィジェットが起きるかという順序は、ウィジェットが入力をプロセスする機会を与えられた順番になります。従って、その時点でフォーカスされたコントロールが配列内の最初のウィジェットであり、次にその親、次にその入力をプロセスできるようなその親の子などとなります。

シーンの InputSubscribers は静的データ ストラクチャではありません。シーンの生存期間中、ウィジェットは常に、シーンの資格のあるウィジェットのリストから追加されたり削除されたりします。ウィジェットがフォーカスを失うと、シーンの資格のあるウィジェットのリストから、削除されます。ウィジェットがフォーカスを得ると、シーンの InputSubscribers のリストに、追加されます。またウィジェットは、状態の変更やウィジェットの内部の論理 (例えば、エディットボックスはテキストボックスに入力される最初の文字は英数字でなければいけないものの、その後の文字は何でもよい、など) に基づいて、処理するイベントのリストへ新しい入力キーを追加したり削除したりすることもできます。これが起きると、ウィジェットはシーンに通知をして、シーンはそれに従って InputSubscribers を調整します。ここでのポイントは、シーンの InputSubscribers はいくつかのイベントの応答としてのみ変更されるということで、ポーリングは必要ありません。入力イベントが起きると、InputSubscribers はすでに最新のものとなっていて、入力をどうすればよいかを決定するのに信頼できるソースとして使用することができます。

入力イベントが受信されると、シーンは InputSubscribers リストから適切な InputEventSubscription を探します。その時点で入力イベントに応答する資格のあるウィジェットのリストをイテレートし、各ウィジェットにイベントをプロセスする機会を与えます。これらのウィジェットは、入力イベントに (もちろん、何らかの理由で応答しないと決めることもありますが) 応答可能であることが保証されています。InputEventSubscription 内のウィジェットのどれもが、入力に応答しない場合、または応答したもののその入力イベントが継続してたらい回しにされるのを許可するように設定されていると、UI システムは GameViewportClient がその入力イベントを配列内の残りのインタラクションに渡すのを可能にします。(入力イベントが処理されたが、順送りされてしまう場合は、その入力イベントを表すイベント オブジェクトは、入力が処理済みであることを示すためにマークされ、どのようなアクションが取られたか、何によって入力が処理されたかなどの情報が含まれる場合もあります。これは何らかの相互タスクを実行するのに、他のゲーム オブジェクトがウィジェットと共に働くことを可能にするために使用されます。繰り返しになりますが、これはウィジェットが応答する入力イベントを捉えないように設定されている場合のみになります。)

プレゼンテーション

プレゼンテーション サブシステムは、UI をユーザーに表示する働きをします。これは、ウィジェットやそれらのリソースのレンダリングや、データ ストアによって提供されたデータのレンダリングを含みます。

シーン

ウィジェットのグループのための最外部のコンテナを UIScene と呼びます。シーンはウィジェットの集まりを含み、シーンとウィジェットの関係は、すべてのウィジェットが UIScene に含まれなければいけないという意味で、マップとマップに設置されたアクタとの関係に非常に似ています。ウィジェットは直接レンダリングすることはできず、常にウィジェットのコンテナ シーンによりレンダリングされます。一度に 1 つ以上のシーンがアクティブになることが可能で、いくつかのシーンはマップの変更を超えて永続することができます。UIScene はエディタ内に作成され、Unreal パッケージ ファイルに格納されるので、UIScene の開き方は、その他の Unreal リソースをゲーム中に読み込む方法とまったく同じです。UIScene はシングル プレイヤーに関連付けられるか、すべてのプレイヤーからグローバルにアクセスされることが可能です。UIScene は、ウィジェットの位置のトラック、アップデート、入力イベントの転送、ウィジェットのレンダリングをします。シーン内のウィジェットは階層的 (ウィジェットは他のウィジェットを含む場合もあります) に整理されていますが、どの入力やレンダリングが各ウィジェットにパスされるかという順序は、(大概はそうであるべきですが) 必ずしもシーンのウィジェットの組織構成によって決定されるわけではありません。

ウィジェット

すべてのウィジェットのベース クラスは UIObject と呼ばれます (多くの場合、ウィジェットと UIObject は同義で用いられます)。

機能:

  • すべてのウィジェットは、他のウィジェットのコンテナとなることが可能です。
  • 各ウィジェットは固有の GUID を有します。
  • 各ウィジェットは、あらゆる状態の数 (押された、アクティブ、フォーカスされた、無効化されたなど) を指定することが可能です。
  • ドッキングするターゲットが同じシーンに含まれている場合、ウィジェットはその他のウィジェットにドッキングすることが可能です。ウィジェットは 1 つ以上のウィジェットにドッキングすることが可能ですが、1 つのウィジェットのドッキングセットの最大数は、そのウィジェットの持つフェイスの最大数と同等です。2D ウィジェットは 4 つのドッキングセットを持つことができます (各面に 1 つずつ)。ソース ウィジェットの 2 面をターゲット ウィジェットの同じ面にバインドできないという制限 (例えば、あるウィジェットのトップと右面の両方を、ターゲット ウィジェットの右面にドッキングするなど) のもとで、1 つのウィジェットは複数のドッキングセットのターゲットになることが可能です。ターゲット フェイスの長さが半分に分けられ、ソース フェイスがターゲット フェイスのそのポイントにドッキングする場合、垂直のフェイスをドッキングすることは可能です。2 つのドッキングセットの間に循環する関係 (WidgetA の左のフェイスが WidgetB の右のフェイスにドッキングされ、WidgetB の右のフェイスが WidgetA の左のフェイスにドッキングする) を作成することはできません。ウィジェットを、自身のドッキングセットの中に含めることはできません。しかしながら、ドッキングの関係が循環でない場合は、WidgetA を WidgetB にドッキングし、WidgetB を WidgetA にドッキングすることは全く問題ありません。コンテナと子の関係 (WidgetA がコンテナで、WidgetB は WidgetA の子) を考えてみてください。WidgetB の左面を WidgetA の左面にドッキングし、WidgetB の右面を WidgetA の右面にドッキングするのが良いでしょう。結果として WidgetA が WidgetB を含むために拡張されたり、収縮したりしますが、WidgetB は WidgetA の左端に、左揃えの状態で残ります。各ドッキングセットにパディング値を指定することもできます。
  • ウィジェットの位置は、ピクセルかパーセンテージで指定することができます。この値は、ビューポート全体、所有しているシーン、または UIObject のコンテナ ウィジェットに関連します。
  • どのウィジェットも、あらゆるイベント (ユーザーとシステムの両方) に応答するように設定することができます。ウィジェット クラスのプログラマは、その特定のクラスがどのイベントに応答可能であるかを決定します。デザイナーは、そのウィジェット クラスのインスタンス内でどのイベントが実装されるかを選択します。または、ウィジェットのプログラマが、1 つ以上のイベント タイプを常に実装するようにウィジェットを決めることができます。
  • 各ウィジェットは特定のイベントに応答して、異なるアクションを実行することが可能です。
  • すべてのウィジェットは、入力をプロセスする能力を持っています。ウィジェットは、常に入力をプロセスするように設定したり、フォーカスされた場合のみ入力をプロセスするように設定したりできます。ウィジェットは、プロセスされた入力とされていない入力の両方を受け入れるかどうかを、選択することができます。
  • 回転、スケール、位置、色、アンカー、UV 座標などのウィジェットのあらゆる属性は、Matinee を使用してアニメーション化することができます。
  • 各ウィジェットに階層のコンテキスト メニュー サポートがあります。
  • すべてのウィジェットはドラッグ & ドロップを適用される場所でサポートします。
  • 含まれるウィジェットのアラインや位置を自動的に調整するように設定できます。

(以下は、利用可能になるすべてのビルトイン ウィジェット クラスに関する参考文献ではなく、いくつかの興味深いクラスの概要となります。)

ラベル

UI にテキストを表示するための基本的なウィジェットです。

  • 含む文字列に合わせるために、サイズの自動調節をサポートしています。
  • 通常 (クリップ)、ラップ、3 点リーダー (文字列の最後のいくつかの文字が 3 点リーダーに取って代わられる) の 3 つのクリップ モードをサポートしています。
  • UIString を基礎としています。

リスト

UIList は、UI を通して設定できるぐらい十分に抽象化されるように、非常に複雑なタイプのリストを一般的な方法でサポートするようなデザインになっています。リストは データ ソース、コンテナ ウィジェット、プレゼンターの 3 つのコンポーネントで構成されています。

  • コンテナ – コンテナは UI へデータを伝えるパイプとして働きます。コンテナは含んでいるデータのタイプに関する知識を持ちません。コンテナは、保有する要素の数と各セルのサイズのトラック、入力の処理 (どの要素が選択されるかのトラックや選択された要素の変更などを含みます)、リストへの要素の追加、リストからの要素の削除、データ ソースとプレゼンターの間にデータのやり取りをします。コンテナは UIList ウィジェットにより、UI 内で表されます。
  • データ – データ ソースは、リストにレンダリングされるデータ値を、リストが取得してくる場所です。いかなるリストにも複数のデータ ソースがあります。リストは、どのデータ ストアにもアクセスがあり、データ ストアは親シーンによりアクセスされることができます。リストのデータ ソースは、UIString クラスにより処理されます。
  • プレゼンター – プレゼンターは、リスト コンテナ内でどのようにデータが表わされるかをコントロールします。プレゼンターは、デザイナーにより構成されたレイアウトに従って、データをフォーマットします。プレゼンターは、リスト コンテナの非動的な制約に従って、リスト コンテナにある動的に調節可能なパラメータの値の調節を処理します。

UIString

UIString は、UI により表わされるすべてのデータ用のコア レンダリングが可能なエンティティです。UIStrings は 1 つ以上の UIStringNodes に分けられており、そこでは各ノードが、通常のテキスト、またはマークアップ データに対応します。マークアップ データは、データ ストアから取り出されるデータにより置換可能なテキストとして定義されています。データ ストアのセクションで前述のように、データ ストアは <DataStoreName:PropertyName> により、参照されます。マークアップは、現在のスタイルを変えたり (<Styles:NormalText>)、スタイル属性を有効化/無効化したり (<Attributes:B> <Attributes:/B>)、マークアップ内で指定されたデータ ストアからのプロパティ値により、マークアップが置換されるべきであることを示したりできます (<SomeDataStoreName:PropertyName>)。UIStrings は入力テキストを解析することにより、UIStringNodes を動的に生成します。例えば、以下の文字列を UIString にパスすると、以下の 7 つのトークン信号が生成されます。
The name specified '<SceneData:EnteredName>' is not available. Press <ButtonImages:IMG_A> to continue or <ButtonImages:IMG_B> to cancel. (指定された名前、'<SceneData:EnteredName>' は利用できません。<ButtonImages:IMG_A> を押して継続するか、<ButtonImages:IMG_B> を押してキャンセルしてください。)
生成されるトークン信号は、以下の通りです。

[0] = "The name specified '"
[1] = "<SceneData:EnteredName>"
[2] = "' is not available.  Press "
[3] = "<ButtonImages:IMG_A>"
[4] = " to continue or "
[5] = "<ButtonImage:IMG_B>"
[6] = "to cancel."

これらのトークン信号は、その後 UIStringNodes に変換されます。データ ストアを参照するマークアップは、そのデータ ストアによりプロセスされます。データ ストアは適切な値が既に記入された UIStringNode を作成します。UIStringNodes には、テキストのレンダリング用と画像のレンダリング用の 2 つのタイプがあります。UIStringNode_Text ノードは、文字列だけでなく、ints、bools などのテキストとしてレンダリングされるデータ値にも使用されます。UIStringNode_Image ノードは、オブジェクトやテクスチャのような画像としてのみレンダリング可能なデータ ストア マークアップ データに使用されます。各文字列ノードは、ポストプロセスされたバージョンのテキストやマークアップに基づいて、自身の正確な範囲値 (幅と高さ) を計算してトラックすることができます。これは、ノードの状態の特定の要素 (データ自身、スケーリング、カーニングなど) が変わったときのみに行われます。その後、完全な UIString の範囲を計算するのは非常に簡単です。すべてのノードの範囲の合計になります。UIString は、各 UIStringNode の範囲を手動でコントロールするように設定することも可能です。例として、デザイナーがセルの特定な域に特定の幅を持たせたかったり、右揃えにしたかったりというような UIListElementCell に含まれている場合などです。

ウィジェット スタイル

スタイルは、ウィジェットがどのように表示されるかをコントロールします。スタイルには、テクスチャ (スケールされる、ストレッチされるなど) をどのようにしてレンダリングするかに関する情報や、文字列 (フォント、色、属性など) を描く情報が含まれます。UI エディタ内には、スタイル ブラウザがあります。ウィジェットにスタイルを適用するには、ユーザーは既存のスタイルのリストから 1 つを選ぶか、新しいスタイル (既存のスタイルを基にするか、完全にまっさらな状態から) を作成することになります。スタイルが作成されると、持続性 GUID に割り当てられます。特定のウィジェット スキン用のすべてのスタイルは、1 つの Unreal パッケージ ファイルに格納されます。スタイルにより必要となるリソースも、スキン ファイルに格納されますが、時により他のパッケージにある場合があります。完全なゲーム UI には、デフォルト スタイル パッケージとして役目を果たすようなスタイル パッケージが、少なくとも 1 つ必要です。いかなる追加のスキン セットはこのデフォルト スキンに基づき、ベース スキンの変更のみがカスタム スキン ファイルに格納されます。ウィジェットがスキン パッケージからスタイルを割り当てられると、ウィジェットの GUID とスタイルの GUID の間のマッピングがスキン ファイルに組み込まれます。カスタム スキン セットに関しては、デフォルトでウィジェットが自動的に、カスタム スタイル セットに含まれているカスタマイズされたバージョンのスタイルにマップしますが、ユーザーは特定のウィジェットにまったく違うスタイルを割り当てることも可能です。これは、このスキン セットのこのウィジェットのスタイルと、このカスタム セットに基づいたスキン セットのみを変更するものです。カスタム セットは、カスタム スキン セットが他のカスタム スキン セットに基づくということから、階層的であると言えます。

スキン

アニメーション

UI エディタ

UI エディタの主要な機能や使用方法を解説しているドキュメントは UI エディタ ユーザー ガイド を参照してください。