【Unity】WebGLをスマホ対応させる4つのポイント

投稿日: 2026年5月5日 対象読者: Unity WebGLをスマホ・タブレットでも動かしたいエンジニア

この記事はこんな方向け:

  • PCでは動くのにスマホで動かない原因を知りたい方
  • タッチ操作をUnity WebGLで実装したい方
  • スマホでの読み込みを速くしたい方

TL;DR

  • Unity WebGLはiOSのSafariでも動作する(Unity 2021以降)
  • スマホ向けには解像度とQuality設定を動的に下げると快適になる
  • タッチ操作は Input.GetTouch() でPC(マウス)とほぼ同じコードで対応可能
  • iOSのSafariはメモリ上限が厳しく、1〜2GBを超えるとタブがクラッシュする

はじめに

Unity WebGLで作ったアプリ、PCでは快適に動くのにスマホで試したら動かない……そんな経験はありませんか?

Pose Mirror の開発でも、スマホ対応は後回しになりがちなポイントでした。いざ対応しようとすると解像度・タッチ・メモリ・Brotliとつまずきポイントが4つも並んでいました。この記事では、Pose MirrorをiOS・Android両対応させるために実施した4つの対応ポイントを実装コード付きでまとめます。

ブラウザ動作確認状況

まず前提として、Unity WebGL(Unity 6)の動作確認環境を共有します。

デバイス ブラウザ 動作状況
iPhone 14 Safari 17 ✅ 動作(読み込み約8秒)
iPhone 14 Chrome ✅ 動作
iPad Air 5 Safari ✅ 動作(PC並みの速度)
Android Pixel 7 Chrome ✅ 動作(読み込み約5秒)
Samsung Galaxy S23 Samsung Browser ✅ 動作

Unity 2021以降であれば、主要なスマホブラウザでの動作は問題ありません。問題になるのはパフォーマンスとメモリです。

ポイント①:解像度とQuality設定を動的に下げる

スマホはGPUの性能がPCより低いため、PC向けの設定のままでは処理が追いつきません。ユーザーエージェントでデバイスを判定し、モバイルのみ設定を下げるのがおすすめです。

// index.html(Unityのローダーファイル)でデバイス判定
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);

createUnityInstance(canvas, {
  dataUrl:      "Build/app.data.br",
  frameworkUrl: "Build/app.framework.js.br",
  codeUrl:      "Build/app.wasm.br",
}).then((instance) => {
  // モバイルの場合はUnityにモード変更を通知
  if (isMobile) {
    instance.SendMessage('GameManager', 'SetMobileMode', '1');
  }
});
// Unity C# 側でモバイル設定を適用
public class GameManager : MonoBehaviour
{
    public void SetMobileMode(string _)
    {
        // 解像度を半分に下げる
        Screen.SetResolution(Screen.width / 2, Screen.height / 2, false);
        // Quality設定を最低レベルに
        QualitySettings.SetQualityLevel(0, true);
    }
}

これだけでフレームレートが2〜3倍改善するケースがあります。

ポイント②:タッチ操作の実装

Unity WebGLはタッチイベントを Input.GetTouch() でそのまま取得できます。マウスと同じロジックで書けるので移植コストが低いです。

void Update()
{
    // PC: マウスドラッグで回転
    if (Input.GetMouseButton(0))
    {
        float deltaX = Input.GetAxis("Mouse X");
        RotateModel(deltaX);
    }

    // スマホ: 1本指スワイプで回転
    if (Input.touchCount == 1)
    {
        Touch touch = Input.GetTouch(0);
        if (touch.phase == TouchPhase.Moved)
        {
            float deltaX = touch.deltaPosition.x * 0.1f;
            RotateModel(deltaX);
        }
    }

    // スマホ: 2本指ピンチでズーム
    if (Input.touchCount == 2)
    {
        Touch t0 = Input.GetTouch(0);
        Touch t1 = Input.GetTouch(1);

        // 前フレームと現フレームの指間距離の差でズーム量を計算
        Vector2 t0Prev = t0.position - t0.deltaPosition;
        Vector2 t1Prev = t1.position - t1.deltaPosition;
        float prevDist = (t0Prev - t1Prev).magnitude;
        float currDist = (t0.position - t1.position).magnitude;

        float pinchDelta = currDist - prevDist;
        Camera.main.fieldOfView =
            Mathf.Clamp(Camera.main.fieldOfView - pinchDelta * 0.05f, 20f, 80f);
    }
}

private void RotateModel(float deltaX)
{
    transform.Rotate(Vector3.up, -deltaX * 100f * Time.deltaTime, Space.World);
}

ポイント③:ビルドサイズの最適化

スマホ回線では大きなファイルの読み込みに時間がかかります。Pose Mirrorでの対応を紹介します。

Brotli圧縮の有効化

Player Settings → Publishing Settings:

  • Compression Format: Brotli

圧縮なし(約30MB)→ Brotli圧縮(約9MB)と、約70%のサイズ削減が可能です。

不要なパッケージを削除する

Package Managerで使っていないパッケージを削除するだけでビルドサイズが下がります。特に以下はデフォルトで入っていることがあるため確認してください:

  • Unity Analytics
  • Advertisement
  • In-App Purchasing
  • Visual Scripting(使っていない場合)

IL2CPP + Managed Stripping Level を上げる

Player Settings → Other Settings:

  • Scripting Backend: IL2CPP
  • Managed Stripping Level: High

使われていないC#コードを除去し、wasmファイルのサイズを削減できます。ただしリフレクションを使っている箇所が削除される場合があるため、ビルド後の動作確認は必須です。

ポイント④:iOSのSafari特有の問題に対応する

iOSのSafariはメモリ管理が厳しく、メモリ上限を超えるとタブが突然クラッシュします。

memorySize を明示的に設定する

createUnityInstance の呼び出し時にメモリ上限を明示します。

createUnityInstance(canvas, {
  dataUrl:      "Build/app.data.br",
  frameworkUrl: "Build/app.framework.js.br",
  codeUrl:      "Build/app.wasm.br",
  // スマホ向けは256〜384MBが安全圏(デフォルトは256MB)
  // 大きくしすぎるとiOSでクラッシュしやすくなる
  memorySize: 256 * 1024 * 1024,
});

AudioContextのAutoplay制限に対応する

iOS Safariはユーザー操作前の音声再生をブロックします。Unityの音声再生は、最初のタップ操作後に開始されるよう設計することが重要です。

// ユーザーのタップ後にAudioContextを再開する
document.addEventListener('touchstart', () => {
  if (typeof AudioContext !== 'undefined') {
    const ctx = new AudioContext();
    ctx.resume();
  }
}, { once: true });

まとめ

  • 解像度・Quality設定をモバイル時に下げると大幅に快適になる
  • タッチ操作は Input.GetTouch() でほぼPCと同じコードで対応可能
  • Brotli圧縮 でビルドサイズを70%削減、読み込み速度を改善できる
  • iOSのメモリ制限に注意し、memorySize を適切に設定する

スマホ対応によって、ユーザーがPCを開かなくても使えるツールになります。ぜひ実際に Pose Mirror をスマホで開いて動作を確かめてみてください!


関連記事:

参考資料

← ポートフォリオ TOP へ戻る