Skip to content

パフォーマンス

パフォーマンスバジェット

初回ロード目標: 2MB以下

Vibe Jam 2026 の要件「ロード画面や重いダウンロードは極力なし」に準拠するため、 初回ロードの合計サイズを 2MB以下(gzip圧縮後)に抑える。

カテゴリバジェット備考
JavaScript(ゲームコア)80KBTypeScript → minify → gzip
JavaScript(Three.js)150KB必要モジュールのみインポート
JavaScript(ポストプロセス)30KBBloom, Glitch 等
テクスチャ・画像500KBWebP形式、遅延ロード
3Dモデル200KB低ポリ、glTF形式
音声300KBOGG/WebM、初回は最小限のみ
HTML + CSS20KB最小構成
合計~1.3MB目標2MBに対して余裕あり

Core Web Vitals 目標

指標目標値計測方法
LCP (Largest Contentful Paint)< 2.5秒ゲームキャンバスの初回描画
FID (First Input Delay)< 100ms初回クリック/タップ応答
CLS (Cumulative Layout Shift)< 0.1レイアウトシフトなし(Canvas固定)
FPS60fps(PC)/ 30fps(モバイル)requestAnimationFrame

アセット最適化戦略

画像フォーマット

フォーマット用途圧縮率対応状況
WebPテクスチャ、UI画像PNGの70~90%削減Chrome/Safari/Firefox 対応
PNGフォールバック、透過必須ベースライン全ブラウザ対応
SVGアイコン、UIパーツ最小全ブラウザ対応

音声フォーマット

フォーマット用途ビットレート対応状況
OGG VorbisBGM、SE96~128kbpsChrome/Firefox
WebM (Opus)BGM(高品質)64~96kbpsChrome/Firefox
AAC/M4ASafari フォールバック96~128kbpsSafari/iOS
typescript
// 音声フォーマットのフォールバック実装例
function loadAudio(basePath: string): string {
  const audio = document.createElement('audio')

  if (audio.canPlayType('audio/ogg; codecs="vorbis"')) {
    return `${basePath}.ogg`
  } else if (audio.canPlayType('audio/mp4; codecs="mp4a.40.2"')) {
    return `${basePath}.m4a`
  }
  return `${basePath}.mp3` // 最終フォールバック
}

遅延ロード戦略

ロード段階タイミング内容サイズ目安
即時ページロードゲームコア + ロビーUI~510KB
遅延シーン遷移時ダンジョンアセット、BGM~500KB
バックグラウンドロビー滞在中次ステージの先読み~300KB

Three.js バンドル最適化

インポート最適化

Three.js は ES Modules 対応しており、Vite の Tree-shaking で未使用コードを除去できる。

インポート方式バンドルサイズ(gzip後)推奨
import * as THREE from 'three'~250KBNG
個別インポート~150KBOK
個別 + 不要機能除外~100KBBEST

必須モジュール一覧

typescript
// レンダリング
import { Scene, PerspectiveCamera, WebGLRenderer } from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

// ジオメトリ・マテリアル
import {
  BoxGeometry, PlaneGeometry, SphereGeometry,
  MeshStandardMaterial, MeshBasicMaterial, ShaderMaterial
} from 'three'

// ライティング
import { AmbientLight, PointLight, SpotLight } from 'three'

// ポストプロセス
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass'

// ローダー
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { TextureLoader } from 'three'

// パーティクル
import { Points, PointsMaterial, BufferGeometry, Float32BufferAttribute } from 'three'

モバイル対応

パフォーマンス段階制御

設定解像度パーティクル数シャドウポストプロセス目標FPS
HIGH100% (1920x1080)1000ON全て60fps
MEDIUM75% (1440x810)300OFFBloom のみ30fps
LOW50% (960x540)100OFFOFF30fps

LOD (Level of Detail)

距離ポリゴン数テクスチャ解像度用途
近距離 (< 5m)100%512x512プレイヤー、近くの敵
中距離 (5~15m)50%256x256遠くの敵、オブジェクト
遠距離 (> 15m)25%128x128背景オブジェクト

ブラウザ互換性マトリクス

対応ブラウザ

ブラウザバージョンWebGL2Web AudiolocalStorage対応レベル
Chrome90+OKOKOKフルサポート
Firefox90+OKOKOKフルサポート
Safari15+OKOKOKフルサポート
Edge90+OKOKOKフルサポート
Chrome Mobile90+OKOKOKMEDIUM設定推奨
Safari iOS15+OK要タップOKMEDIUM設定推奨
Samsung Internet15+OKOKOKMEDIUM設定推奨

既知の制約

ブラウザ制約対策
Safari iOSWeb Audio はユーザー操作後のみ再生可タップで AudioContext を resume
Safari iOSストレージ容量が制限的(7日間未使用で削除)プレイ毎に localStorage を touch
FirefoxSharedArrayBuffer 制限使用しない設計
全モバイルタッチ操作バーチャルジョイスティック実装

localStorage データ戦略

容量管理

ブラウザlocalStorage 上限Rift Survivors 使用量余裕
Chrome5MB~4KB99.9%
Firefox5MB~4KB99.9%
Safari5MB~4KB99.9%
Mobile2.5~5MB~4KB99.8%

データクリーンアップ

typescript
// localStorage のバージョン管理
const STORAGE_VERSION = 'v1'
const STORAGE_PREFIX = 'rift_'

function initStorage(): void {
  const version = localStorage.getItem(`${STORAGE_PREFIX}version`)

  if (version !== STORAGE_VERSION) {
    // バージョン不一致時はデータをマイグレーション or リセット
    migrateData(version, STORAGE_VERSION)
    localStorage.setItem(`${STORAGE_PREFIX}version`, STORAGE_VERSION)
  }
}

function getStorageUsage(): number {
  let total = 0
  for (const key in localStorage) {
    if (key.startsWith(STORAGE_PREFIX)) {
      total += localStorage[key].length * 2 // UTF-16
    }
  }
  return total // bytes
}

// 最大使用量: 100KB(安全マージン)
const MAX_USAGE = 100 * 1024

データ構造

json
{
  "rift_version": "v1",
  "rift_character": {
    "name": "Player",
    "level": 15,
    "exp": 4500,
    "stats": { "hp": 200, "atk": 45, "def": 30, "spd": 12 }
  },
  "rift_equipment": {
    "weapon": { "id": "sword_003", "rarity": "rare", "level": 8 },
    "armor": { "id": "armor_001", "rarity": "common", "level": 5 },
    "inventory": [...]
  },
  "rift_progress": {
    "completedMissions": ["mission_01", "mission_02"],
    "unlockedAreas": ["lobby", "dungeon_1"]
  },
  "rift_settings": {
    "volume": { "bgm": 0.7, "se": 1.0 },
    "quality": "high",
    "language": "ja"
  }
}

パフォーマンス監視

開発時の計測

ツール用途
Chrome DevTools PerformanceFPS、メモリ使用量の計測
LighthouseCore Web Vitals の計測
vite-plugin-bundle-analyzerバンドルサイズの可視化
Three.js renderer.infoドローコール、トライアングル数の確認

ランタイム計測(組み込み)

typescript
// FPSカウンター(開発モードのみ)
class PerformanceMonitor {
  private frames = 0
  private lastTime = performance.now()

  update(): void {
    this.frames++
    const now = performance.now()
    if (now - this.lastTime >= 1000) {
      const fps = this.frames
      this.frames = 0
      this.lastTime = now

      if (fps < 24) {
        console.warn(`Low FPS: ${fps} - consider reducing quality`)
        this.suggestQualityReduction()
      }
    }
  }

  private suggestQualityReduction(): void {
    // 自動品質調整: FPSが低下したら設定を下げる
  }
}