1. 重くしない(ワールド環境)
毎フレーム動く処理を作らない
Updateは使わないのが基本です。時計などは、見えているときだけ、必要な間隔(秒の表示なら1秒、分なら1分)でSendCustomEventDelayedSecondsを回します- 分や日付の変わり目は、App Services の合図(
_OnServicesMinute・_OnServicesDayChanged)を使います。アプリごとにタイマーを回さないでください - どうしても
Updateが要るときは、中身を別のメソッドにしてPerfBegin(); 中身(); PerfEnd();で囲みます(開発者向けの表示で、そのアプリの時間が測れます)
閉じているときは何もしない
- アプリを閉じると、画面は OS が非表示にします。そのあいだ処理を走らせないでください
- 重い準備は、ワールドに入ったときではなく、初めて開いたときにします
画面の作り直しを小さく
- よく変わる部分(時計・再生位置・ローディング)は小さい Canvas に分けます
- Layout Group・Content Size Fitter は、エディタで並べ終えたら実行中は使いません
- 届いたデータは、変わったところだけ画面にはめます
feed は小さく
- 目安は 1ファイル 50KB 以内。端末で使わない項目は入れません
2. 読み込みの枠を分け合う
| 種類 | 決まり |
|---|---|
| 文字列(feed) | VRChat の決まりで 5秒に1回。共通の feed が最優先で、残りを全アプリで分け合う。読む間隔はマニフェストの data に書き、OS が順番を組む |
| 画像 | ワールド全体で5秒に1枚、最大 2048×2048。App Services の _RequestImage で頼む(自分で読まない) |
| 読めるドメイン | 文字列は *.github.io・Gist・Pastebin・*.vrcdn.cloud・*.disbridge.com だけ。画像は VRChat の信頼済みドメイン(i.ytimg.com など)だけ |
画像の扱い:
- 小さい画像(サムネイル・アイコン)は OS が置き場に残し、同じ URL は1回しか読みません。置き場の上限(PC 64MB・Quest 24MB)を超えると、長く使っていないものから捨てられます。画面の側は「置き場になければ頼む」作りにしてください(一度頼んだら二度と頼まない作りは、捨てられたときに困ります)
- 大きい画像(地図に重ねる画像など)は、画面を離れたら使わないでください
- サムネイルは用が足りるいちばん小さい種類を使います(YouTube なら
mqdefault)
3. 保存の予算
VRChat の PlayerData は、1ワールド・1人あたり 100KB を、そのワールドのすべてのギミックで分け合います。Ulexite はそのうち 60KB までしか使わない約束で、内訳は次のとおりです。
| 使う人 | 量 |
|---|---|
| システム(OS・設定・同意・ストア) | 16KB |
| アプリ1つ | 標準 4KB。マニフェストの budget.saveKB で申告すれば最大 16KB |
- 保存は App Services の保存の窓口を使います。キーは OS がアプリごとに分けます(
ulexite_<アプリID>_...) - 何かが1つ変わると全部の PlayerData が送られるので、頻繁に変わる値は保存しないでください
OnPlayerRestoredの前に読み書きしないでください
4. 同期
- 画面の状態(開いているアプリ・フォーカス・タブ)は OS が同期します。アプリで書く必要はありません
- アプリの小さな状態は 1バイトの
AppStateで同期できます。それ以上は App Services の共有データを使い、量はbudget.syncBytesで申告します - ネットワークイベントで呼ぶメソッドには
[NetworkCallable]を付け、届いた値は必ず範囲を確かめます。呼ばれたくないメソッドは名前を_で始めます
5. 例外で止まらない
Udon では、例外が出た UdonBehaviour はそのセッションのあいだ止まります。
- 配列の範囲、null、外から届いた値は、使う前に確かめます
- 止まったアプリは OS が閉じて「応答がありません」と出します。ほかのアプリと OS は動き続けます
6. 外部のサービスとデータの決まり
| 相手 | 決まり |
|---|---|
| YouTube | 名前とロゴの扱いに注意。アセット名・パッケージ名に「YouTube」「YT」を入れない。ロゴは公式素材をそのまま使う。ページをスクレイピングしない(データは公式 API だけ。API のデータは30日以内に更新か削除)。サムネイルをテクスチャとして焼き込まない |
| 気象庁 | ロゴ・キャラクターを使わない。警報・注意報は発表をそのままの形で伝え、独自の判定・予測・要約をしない(気象業務法) |
| VRChat のイベントカレンダー | 許可なく取得・表示しない |
| 効果音・素材 | 再配布が許されていないもの(効果音ラボの音源など)を同梱しない。差し替えの枠だけ用意する |
- 外部のデータや素材を使うときは、アプリの画面に出典を表示し、
NOTICE.txtにも書きます(例:「出典:気象庁ホームページ」) - 外部から来た文字列(タイトルなど)を TextMeshPro に出すときは、リッチテキストを無効にするか
<をエスケープします
7. アプリの行儀
- App Services だけを使う。シェルや OS の土台、ほかのアプリを直接呼ばない
- ほかのアプリを開くときは、アプリ間の呼び出しの窓口を使う
- Ulexite TV 本体(
vrc.ulexite.tv)のファイルを書き換えない。足りない機能は Ulexite に要望を出してください - アプリ ID は公開後に変えない(保存のキーに使われているため)
Companion とアバター端末の権限は、公開時にまとめます。