本文へスキップ

UI

はじめに

8th Wall Studioは、インタラクティブでユーザーフレンドリーなインターフェースを作成するためのUIシステムを内蔵しています。

UIレイアウトとコンポーネント

Studioには、テキストや画像からボタンやフレームまで、さまざまなUIビルディングブロックが用意されています。 階層パネルの直感的な(+)オプションにより、UI要素の追加やカスタマイズが簡単に行えます。 UI Element Componentには、CSSとFlexboxにインスパイアされた詳細な設定項目があり、ボーダーから背景色まですべてを調整できます。 フレックスボックスのスタイリングについては、こちらを参照してください。

UI要素の追加

UI要素を導入するには、いくつかの方法がある:

  • **ビジュアルエディター:**プリセットを追加するには、階層の(+)オプションを使用します。
  • コンポーネントメソッド: UI 要素をコンポーネントとしてエンティティにアタッチします。
  • スクリプティング: APIを使用してプログラムで要素を追加します。

add-ui-elements.png

3D UI

3D UIエレメントは3Dシーンにシームレスに統合され、空間的にインタラクティブな表示が可能になります。 インスペクタやトランスフォーム・ギズモで調整できます。

ui-element-mode-3d

交流

イベントリスナーを持つカスタムコンポーネントを使用して、3D UI要素にインタラクションを追加できます。

import * as ecs from '@8thwall/ecs'

ecs.registerComponent({
name: '3D Button',
schema: {
},
schemaDefaults: {
},
data: {
},
stateMachine: ({world, eid}) => {
ecs.defineState('default')
.initial()
.listen(eid, ecs.input.SCREEN_TOUCH_START, (e) => {
console.log('Interacted!')
})
},
})

オーバーレイUI

スクリーンに固定されたUIでは、オーバーレイ要素は絶対位置決めを提供します。 シミュレータ内でこれらの要素をプレビューし、レスポンシブデザインのためにパーセンテージベースのサイジングを使用します。

ui-element-mode-2d

交流

イベントリスナーを持つカスタムコンポーネントを使用して、Overlay UI 要素にインタラクションを追加できます。

import * as ecs from '@8thwall/ecs'

ecs.registerComponent({
name: 'Overlay Button',
schema: {
},
schemaDefaults: {
},
data: {
},
stateMachine: ({world, eid}) => {
ecs.defineState('default')
.initial()
.listen(eid, 'click', (e) => {
console.log('Interacted!')
})
},
})

ステートマシンとの統合

このページの前の例で見たように、UIはステートマシンと統合して、下の写真のような基本的なメニューナビゲーションなどの機能を実装することができる。

UIコンポーネントで作られたこれらのボタンは、操作されたときにイベントをディスパッチするように設定できる。

ecs.registerComponent({
name: 'start-button',
stateMachine: ({world, eid}) => {
ecs.defineState('default')
.initial()
.listen(eid, ecs.input.UI_CLICK, () => {
world.events.dispatch(eid, 'onStartButtonClick')
})
},
})

Studioで作成されたUIメニューは、状態別に追跡および整理することができます。

enum GAME_STATES {
GAME_START = 'gameStateStart',
GAME_ACTIVE = 'gameStateActive',
GAME_OVER = 'gameStateOver',
}

enum GAME_MENUS {
START_MENU = 'startMenu',
GAME_OVER_MENU = 'gameOverMenu',
}.

他のすべてのメニューを非表示にし、アクティブにしたい1つのメニューを表示することで、メニュー間の切り替えを容易にするために、プログラムで非アクティブなすべてのメニューを非表示にする関数を使用することができます。

const updateUI = (world, schema, activeMenu = null) => {
Object.values(GAME_MENUS).forEach((menu) => {
if (schema[menu]) {
if (menu === activeMenu) {
ecs.Hidden.remove(world, schema[menu])
} else {
ecs.Hidden.set(world, schema[menu])
}.
} else {
console.warn(`Menu ${menu} is not defined in the schema.`)
}.
})
}

上記はすべて、ボタンのクリックやゲームの状態によって変化するメニューナビゲーションのステートマシンを管理するために使用できる。 次の例では、スタートボタンをクリックするとゲームが始まり、設定した時間が経過するとゲームオーバーメニューが表示されます。 ゲームオーバーメニューからは、さらにボタンでゲームを再開したり、スタートメニューに戻ったりすることができる。

ecs.registerComponent({
name: 'game-controller',
schema:{
startMenu: ecs.eid,
gameOverMenu: ecs.eid,
gameActiveMenu: ecs.eid,
},
data: {
isGameActive: ecs.boolean,
},
stateMachine: ({world, eid, dataAttribute, schemaAttribute}) => {
const gameOver = ecs.defineTrigger()

ecs.defineState(GAME_STATES.GAME_START)
.initial()
.onEnter(() => {
console.log('ゲームスタートに入った')
updateUI(world, schemaAttribute.cursor(eid), GAME_MENUS.START_MENU)
})
.onEvent('onStartButtonClick', GAME_STATES.GAME_ACTIVE, {target: world.events.globalId})

ecs.defineState(GAME_STATES.GAME_ACTIVE)
.onEnter(() => {
console.log('状態変化: Entered Game Active')
updateUI(world, schemaAttribute.cursor(eid), 'gameActive')

setTimeout(() => {
console.log('Waiting done. Triggering game over.')
gameOver.trigger()
}, 1000)
})
.onTrigger(gameOver, GAME_STATES.GAME_OVER)

ecs.defineState(GAME_STATES.GAME_OVER)
.onEnter(() => {
dataAttribute.cursor(eid).isGameActive = false
updateUI(world, schemaAttribute.cursor(eid), GAME_MENUS.GAME_OVER_MENU)
})
.onEvent('onRestartButtonClick', GAME_STATES.GAME_ACTIVE, {target: world.events.globalId})
.onEvent('onReturnStartClick', GAME_STATES.GAME_START, {target: world.events.globalId})
},
})

フォント

デフォルトフォント

デフォルトのフォントは、UIシステム内で使用できます。

Nunito

Nunito.png

Akidenz Grotesk

AkidenzGrotesk.png

Baskerville

Baskerville.png

Futura

Futura.png

Gotham

Gotham.png

Helvetica

Helvetica.png

Nanum Pen Script

NanumPenScript.png

Press Start 2P

PressStart2P.png

Times

Times.png

Inconsolata

Inconsolata.png

カスタムフォント

また、TTFファイルを介してカスタムフォントをアップロードし、UIエレメントで使用することもできます。 カスタムフォントファイルをアセットに追加して、利用できるようにしましょう。