考え方
- 計算はサーバーで済ませる。月齢、日の出、METAR の読み解きなどは、feed を作るサーバー側で計算して値として入れておきます。端末の上では計算しません(式もスクリプトも書けません)
- 画面は「型」を選んで「部品」をはめる。自由な配置はできません。そのかわり、見た目とリモコンの操作が Ulexite のほかの画面とそろい、フォーカスの順番も OS が決めます
- 画面はエディタで作られる。ワールドでは、テレビを作るときに Ulexite が定義を読んで画面を組み立て、焼き込みます。実行中に起きるのは「データを読んで、変わった値をはめる」ことだけです。だから重くなりにくいのです
- URL はすべて焼き込み。Udon は実行中に URL を作れないので、読むファイル・画像の URL は定義の
assetsに全部書いておきます。地点ごとにファイルが違う場合も、地点の数だけ URL を書き出します(each)
ファイルの並び
Packages/vrc.ulexite.app.weather/
package.json VPM のパッケージ情報(バージョンと作者はここが正)
ulexite-app.json マニフェスト。kind: declarative、runtimes.world.screens に定義のファイル
app.screens.json 画面の定義(この章の本題)
lang.json 翻訳表
feed.sample.json feed の見本(エディタの検査とプレビューに使う)
Textures/ アイコンなど
NOTICE.txt データや素材の出典
マニフェストでは、kind を declarative にして、runtimes.world.screens に定義のファイルの名前を書きます。
"kind": "declarative",
"runtimes": { "world": { "os": 1, "appServices": 2, "screens": "app.screens.json" } }
定義のファイルの骨組み
{
"format": 1,
"lang": "lang.json",
"settings": [ ... ], // アプリの設定項目
"assets": { ... }, // 読むファイル・画像の URL(すべて焼き込み)
"data": [ ... ], // いつ、どのファイルを読むか
"maps": { ... }, // 値 → 文字・色・アイコンの対応表
"tile": { ... }, // ホームのタイルに出すもの
"screen": { ... } // 画面
}
画面の型
| 型 | 使いどころ | 例 |
|---|---|---|
tabs | 上にタブ、下にそれぞれの画面。中に別の型を入れる | 天気(天気/月/地震/地図) |
list-detail | 左に一覧、右に選んだものの詳細 | METAR、地震 |
dashboard | カードの並び(数値・短い文・小さな表) | 月の満ち欠け |
map | 地図の下地に、画像・点・印を重ねる | 雨雲、震源 |
grid | タイルの格子 | ライブカメラ(まだ使えません) |
型は入れ子にできます。天気アプリの「天気」タブは、tabs の中に list-detail があり、その詳細が dashboard です。
"screen": {
"type": "tabs",
"title": "t:weather.name",
"tabs": [
{ "id": "forecast", "label": "t:weather.tab.forecast",
"screen": {
"type": "list-detail",
"list": { ... },
"detail": { "type": "dashboard", "cards": [ ... ] }
} }
]
}
部品
| 部品 | 内容 | 状態 |
|---|---|---|
text | 文字。style で caption(補足)・title・strong など | 使える |
value | 大きな数値と単位(と、横のアイコン) | 使える |
icon | 同梱のアイコンを名前で | 使える |
badge・badges | 色つきの札(警報の種類など) | 使える |
strip | 横並びの小さなカード(週間予報など) | 使える |
list | 一覧 | 使える |
note | 出典・注意書き | 使える |
image | assets の画像 | まだ |
chart | 折れ線・棒(点は12まで) | まだ |
button | 動作を呼ぶボタン | まだ |
custom | U# で書いた部品をはめる | まだ |
dashboard のカードの例(今の天気):
{ "size": "wide", "parts": [
{ "text": "{{ selected.area | choice:jma-areas }}・{{ t:weather.now }}", "style": "caption" },
{ "value": "{{ area.current.temp | num:0 }}", "unit": "℃", "icon": "{{ area.current.wx | map:wxIcon }}" },
{ "text": "{{ area.current.wxText }}" }
] }
値のはめ込み
{{ }} の中に、値の道筋を書きます。
| 書き方 | 指すもの |
|---|---|
{{ area.current.temp }} | data の id が area の feed の、current.temp |
{{ area.days[0].max }} | 配列の0番目 |
{{ settings.areas[0] }} | 設定の値 |
{{ item.name }} | 一覧・strip の中で、その1件 |
{{ selected.area }} | 一覧で選んでいるもの(一覧に "select": "area" と書いたとき) |
{{ common.warnings[selected.area] }} | 道筋の中に、別の値を差し込む(式は書けません。差し込みだけ) |
{{ common.quakes }} | 共通の feed(地震・津波・警報など) |
t:weather.now | 翻訳表のキー |
整形
| でつなぎます。使えるのは OS が用意した関数だけです。
| 関数 | 例 | 結果 |
|---|---|---|
num:桁 | {{ 18.44 | num:1 }} | 18.4 |
unit:単位 | {{ 18 | unit:℃ }} | 18℃ |
time | {{ "2026-10-18T21:20:00+09:00" | time }} | 21:20 |
time:dayAware | 昨日の時刻 | 昨日 23:51 |
date・date:weekday・date:short | 10月19日・月・10/19 | |
ago | 3分前 | |
map:表の名前 | {{ "100" | map:wxIcon }} | sun |
choice:選択肢の表 | {{ "130000" | choice:jma-areas }} | 東京都 |
scale:名前 | {{ 31 | scale:temp }} | 温度の色の段階 |
値がないときは「—」、データがまだ1つも読めていないときは「読み込み中…」、読めなかったときは「読み込めませんでした」を OS が出します。アプリで気にする必要はありません(古いときの「〇時〇分の情報」の表示は準備中)。
対応表 maps
値を、文字・色・アイコンに対応させます。"*" は「それ以外」です。
"maps": {
"wxIcon": { "100": "sun", "200": "cloud", "300": "rain", "400": "snow", "*": "cloud" },
"warnColor": { "special": "level5", "danger": "level4", "warning": "level3", "advisory": "level2" }
}
色は意味の名前で書きます:danger・warning・caution・info・muted。実際の色はテーマとユーザー補助(色の見分けやすさ)に合わせて OS が決めます。凡例など、色そのものに意味があるところだけ #rrggbb を使えます。
警報・注意報には、気象庁のレベルの色に合わせた level5(特別警報・黒)・level4(危険警報・紫)・level3(警報・赤)・level2(注意報・黄)を使います。この4つはテーマで変わりません。色だけに頼らず、気象庁の名前(「レベル4大雨危険警報」など)を必ず一緒に出してください。
震度には int1〜int7 を使います(int5l・int5u、int6l・int6u は「5弱」「5強」「6弱」「6強」)。
札の文字の色は OS が決めます。アプリから文字の色は指定できません。level5・level4・level3 と int1・int2・int3・int5u・int6l・int6u・int7 は白、level2・int4・int5l は暗い色になり、level5 は明るい線で囲まれます(暗い画面に沈むため)。danger・warning・caution・info・muted は今までどおりです。文字が入りきらないとき(震度の「5弱」など2文字)は OS が自動で小さくする(約 0.75 倍)ので、大きさは指定しません。
表示の条件 when
道筋を書くと、その値があって、空でも false でもないときだけ表示します。比較(「震度4以上なら」など)は書けません。絞り込みが必要なら、サーバーで別の欄を作ってください。
{ "size": "wide", "when": "common.warnings[selected.area]", "style": "alert", "parts": [ ... ] }
設定
"settings": [
{ "id": "areas", "type": "order", "scope": "global", "max": 3,
"choices": "jma-areas", "default": ["130000"], "label": "t:weather.setting.areas" }
]
type:choice(選択肢)・toggle(オン・オフ)・order(選んで並べる)scope:必ず書きます。local(各自)・global(全員共通)・creator(ワールドの制作者が Unity で決めて焼き込む)- テレビは全員で見るので、画面に出る一覧は
globalにするのが基本です(選んでいる項目はもともと全員で同期するため、各自の一覧だと人によって別のものを指して壊れます)。localは音量のように、画面の見え方が人によって変わらないものに使います orderはpickの選択ダイアログで、入っていない項目は末尾に足され、入っている項目(✓)は決定で消えます。最後の1つは消せません(1件以上)。maxを超えて足そうとすると「これ以上入りません」とトーストが出ます。並び順は入れた順で、並べ替えは共通のダイアログではできません(アプリの画面側でsetするか、消して入れ直します)- 各自の設定は PlayerData に保存されます(保存の予算は 7章)
読むファイルとタイミング
"assets": {
"files": {
"area": { "each": "jma-areas", "url": "https://thesilver0913.github.io/ulexite-catalog/v1/feed/weather/{{key}}.json" },
"map": { "url": "https://thesilver0913.github.io/ulexite-catalog/v1/feed/weather-map.json" }
}
},
"data": [
{ "id": "area", "file": "area[{{selected.area}}]", "every": "10m" },
{ "id": "map", "file": "map", "every": "10m", "when": "screen:map" },
{ "id": "now", "file": "area[{{settings.areas[0]}}]", "every": "10m", "background": true }
]
assets.files:URL を焼き込みます。eachを書くと、選択肢の表の数だけ URL を書き出します({{key}}に表のキーが入る)data:everyは読む間隔、when: "screen:map"は「その画面を開いているときだけ」、background: trueは「アプリを閉じていても読む」(ホームのタイル・通知用。必要なものだけにする)- URL は信頼済みのドメインだけ(
*.github.ioなど。7章)。エディタが検査します - 読み込みはワールド全体で5秒に1回の枠を分け合います。間隔は短くしすぎないでください(目安10分)
feed の形
feed はサーバーが作る JSON です。ほかの作者のアプリの feed は、アプリの開発者が信頼済みドメイン(自分の GitHub Pages など)に置き、URL を定義に書きます。共通の feed は Ulexite 公式が用意するものだけです。決まりは3つです。
versionを入れる。項目は足すだけにして、意味を変えない- 計算済みの値を入れる(端末は計算しない)
- 小さく保つ(目安 1ファイル 50KB 以内)
{
"version": 1,
"updatedAt": "2026-10-18T21:20:00+09:00",
"current": { "temp": 18.4, "wx": "200", "wxText": "くもり" },
"days": [ { "date": "2026-10-18", "wx": "200", "max": 21, "min": 14, "pop": 30 } ],
"sun": { "rise": "05:49", "set": "17:08" }
}
ホームのタイル
"tile": {
"icon": "{{ now.current.wx | map:wxIcon }}",
"text": "{{ now.current.temp | num:0 | unit:℃ }}"
}
確かめ方
- 定義と同じフォルダに feed の見本を置きます:
feed.sample.json(全部の data)、feed.<data の id>.sample.json(その data だけ)、common.sample.json(共通の feed) - Tools → Ulexite → データで書くアプリのプレビュー で、Play せずに見本の値をはめた画面が見られます。タブや選んでいる行も切り替えられます
- 同じ窓に検査の結果が出ます:道筋が見本に実在するか、URL のドメイン、文字のはみ出し
- Tools → Ulexite → テレビを作り直す(再設置と再紐づけ) でテレビに組み込み、ClientSim や Build & Test で確かめます
地図(map 型)
- 下地は OS が持っています:
"base": "world"(世界)・"japan"(日本)。図法の計算も OS がするので、アプリは緯度・経度を書くだけです - 重ねるもの:
image(透明な画像。framesでコマ送り)、points(緯度・経度と値の点)、marker(震源などの印) - 右の切り替えと凡例は OS が並べます
画面の状態の同期
開いているタブ、一覧で選んでいるもの、地図に重ねているものは、シェルが全員に同期します(全員が同じテレビを見ているため)。アプリで同期を書く必要はありません。
よくある質問
Q. 「震度4以上だけ」のように絞り込みたい
A. 書式では絞り込めません。サーバーで quakes4plus のような欄を作ってください。
Q. 画像を feed から出したい
A. URL は焼き込みなので、feed からは assets の画像の ID を指します。feed の中に URL を書いても読めません。
Q. ボタンを押して何かしたい
A. 動作は OS が用意したものだけです:open(同じアプリの別の画面)、openApp(ほかのアプリを開く)、play(再生)、set(設定を変える)、pick(選択肢を選ぶ画面)。今使えるのは、一覧の下のボタン(footer)の pick だけです。button 部品と、ほかの動作は準備中です。