【Unity】WebGLでピンチズームが効かない原因と解決法|touch-action:none一行で直る
投稿日: 2026年6月23日(2026年10月5日更新)
対象読者: Unity WebGLをスマホ対応させていて、2本指ピンチが効かずに困っているエンジニア
不具合内容
Unity WebGLをスマホのブラウザで開くと、2本指のピンチズームが効かない。3Dモデルは拡大されず、代わりにページ全体がズームしてしまう。1本指のスワイプ(回転)は正常に動く。
原因
- スマホのブラウザが2本指のタッチを「ページのピンチズーム」として先に処理し、canvasまでタッチが届かない。Unityから見ると
Input.touchCountが2にならない
解決方法
- Unity WebGLの描画先
#unity-canvasに、CSSでtouch-action: none;を1行足す。C#側の修正は要らない - viewport の
user-scalable=noは、ページ全体のズームを禁止する設定で、要素の上のジェスチャの扱いを決めるものではない
動作環境
| 項目 | 内容 |
|---|---|
| Unity | 6000.0.58f2 (WebGLビルド) |
| 対象 | スマホのブラウザ での2本指タッチ |
| 修正箇所 | PoseMirror の app.css (#unity-canvas) |
解決方法の詳細:canvas にtouch-action: none を指定する手順
2本指のタッチが Unity に届くようにする手順を説明し、そのあとに不具合の再現手順を載せます。
手順1:#unity-canvas のスタイルを書いているCSS を開く
Unity WebGLは、index.html の中の <canvas id="unity-canvas"> に3Dを描画します。このcanvasのスタイルは、Unity標準のWebGLテンプレートなら TemplateData/style.css に書かれています(Unity 6000.0.58f2 の Default テンプレートで確認)。
/* Unity標準テンプレートの TemplateData/style.css(抜粋) */
#unity-canvas { background: {{{ BACKGROUND_COLOR }}} }
.unity-mobile #unity-canvas { width: 100%; height: 100% }
どのテンプレートが使われるかは、Unityの「Edit → Project Settings → Player」でWebGLのタブを開き、「Resolution and Presentation」の「WebGL Template」で決まります。
ビルド後のフォルダを直接編集すると、次のビルドで上書きされて消えます。自前のWebGLテンプレート(Assets/WebGLTemplates/テンプレート名/)を使っている場合はそちらのCSSを、PoseMirror のようにビルドを別のページに埋め込んでいる場合は、そのページのCSSを編集します。
手順2:touch-action: none; を1行足す
#unity-canvas のスタイルに touch-action: none; を追加します。C#側の修正は要りません。
#unity-canvas {
width: 100% !important;
height: 100% !important;
display: block;
object-fit: contain; /* 歪みを防止 */
touch-action: none; /* モバイルのピンチをUnityへ渡す(ページズームに奪わせない) */
}
touch-action: none; は、この要素の上ではブラウザがスクロールもピンチズームもしない、という指定です。ブラウザがジェスチャを横取りしなくなるので、2本指のタッチが canvas を通って Unity に届きます。
手順3:公開し直す
CSSを直したファイルを、Unity WebGLを公開している場所(Firebase Hosting など)へアップロードし直します。スマホのブラウザはCSSをキャッシュしていることがあるので、確認前に再読み込みします。
確認1:スマホで2本指ピンチをして、3Dだけがズームする
スマホのブラウザでページを開き、3Dの上で2本指ピンチをします。ページ全体ではなく3Dモデルだけが拡大・縮小されれば成功です。Unity 側では Input.touchCount が 2 になり、下の「再現1」の C# のコードが動きます。
PoseMirror では、この1行を #unity-canvas に足しただけでピンチズームが効くようになりました。
参考:viewport のuser-scalable=noとは役割が違う
ページのズームを止めたいなら、viewport の user-scalable=no でもよいのでは、と思うかもしれません。この2つは役割が違います。
<!-- ページ全体のズームを禁止する(ページ単位の設定) -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
| 設定 | 効果 | 用途 |
|---|---|---|
user-scalable=no(viewport) |
ページ全体のユーザーズームを禁止 | サイト全体でズームさせたくない時 |
touch-action: none(CSS) |
指定要素のブラウザ標準ジェスチャを無効化し、イベントを要素に渡す | canvasだけにタッチを渡したい時 |
user-scalable=no は、ページ全体のズームを禁止する設定です。canvas の上の2本指を canvas に渡すかどうかは、touch-action が決めます。ページ全体のズームを禁止すると、文字を拡大して読みたい人が困るという問題もあります。PoseMirror では viewport は initial-scale=1.0 のまま(ページのズームは許可)にして、canvas にだけ touch-action: none を指定しています。
原因詳細:ブラウザが2本指ジェスチャを横取りしている
不具合は次の手順で再現できます。
再現1:Unity 側にピンチの処理を書く
PoseMirror のカメラ操作(MouseLook.cs)のピンチ処理です。2本の指の間隔が変わった分だけ、カメラとモデルの距離を変えています。この処理自体に問題はありません。
void Update()
{
// スマホ: 2本指ピンチでズーム
if (Input.touchCount == 2)
{
Touch t0 = Input.GetTouch(0);
Touch t1 = Input.GetTouch(1);
Vector2 p0Prev = t0.position - t0.deltaPosition;
Vector2 p1Prev = t1.position - t1.deltaPosition;
float prevDist = (p0Prev - p1Prev).magnitude;
float curDist = (t0.position - t1.position).magnitude;
float h = Mathf.Max(1f, Screen.height);
// 指を広げる(curDist > prevDist)=ズームイン=カメラを近づける
distance -= ((curDist - prevDist) / h) * pinchSpeed * distance;
distance = Mathf.Clamp(distance, minDistance, maxDistance);
}
}
再現2:touch-action を指定せずにスマホで開き、2本指ピンチをする
canvas に touch-action を指定しないまま公開し、スマホのブラウザで2本指ピンチをします。3Dモデルは拡大されず、ページ全体がズームします。1本指のスワイプ(回転)は動くので、C# のコードを疑いがちです。PC の Unity エディタではピンチを試せないので、スマホで開いて初めて気づきます。
なぜピンチが効かないのか
Unity の処理に問題はありません。Input.touchCount が 2 になっていないのが原因です。
スマホのブラウザは、2本指のタッチを、ページのピンチズームというブラウザ標準のジェスチャとして先に処理します。ブラウザがジェスチャを処理すると、ページ側へのタッチは途中で打ち切られます(MDN の touch-action の説明を参照)。Unity から見ると2本指のタッチが来ていない状態になり、ピンチの処理が動きません。
1本指でなぞる回転は動き、2本指だけが効かない。この症状が、ブラウザがジェスチャを横取りしているサインでした。
タッチがどこで消えているかを図にするとこうなります。
まとめ
Unity WebGL でピンチが効かないときは、Unity の C# より先に、ブラウザがジェスチャを横取りしていないかを疑います。#unity-canvas に touch-action: none; を1行足せば、2本指のタッチが Unity に届きます。viewport の user-scalable=no は役割が違う設定なので、ページのズームは許可したまま、canvas にだけ指定するのがおすすめです。
読み込むファイルを小さくする方法は、【Unity】Webアプリで表示するための軽量化方法にまとめています。この対応を入れたツールは、PoseMirror でスマホから触れます。
