この記事は、Unity - Qiita Advent Calendar 2025 - Qiitaのシリーズ2の4日目の記事です。
- 前の日は、tsubaki_t1 - QiitaさんのUtility AIです。
- 次の日は、nattoufu - Qiitaさんの音ゲーを創る[基本実装編]です。
11月に開催された技術書典19で、パズルゲームのステージの作り方を解説する趣味のゲーム開発:レベルデザイン編 パズルゲームのステージを作ろう!:アミューズワンという同人誌を出版しました。
この本の中で作成したステージを、実際に遊べるようにWebGLにビルドして、こちら(https://am1tanaka.github.io/VBirdHiyokoStageBook/digiga2025/index.html)で公開しています。
Unityは、WebGLビルドに力を入れていて、PCは当然のこと、スマホのWebブラウザーでも結構動きます。これで、スマホでも手軽に遊んでもらえると思っていたのですが、公開してから、タッチ操作に対応していないことに気づきました。本記事は、その対応方法をまとめたものです。
目次
動作環境
動作環境は、次のとおりです。
- Unity 6.0.58f2
- Input System 1.14.2
- InputActionにアクションを定義して利用
動かなかった原因
WebGLビルドしたものが、スマホのWebブラウザー上でも動くようにできるだけ頑張ってはいますが、公式にはサポートされていません。ということで、油断してました。動作していない状態のInputActionは、次のとおりでした。

ClickとPointとTapの3種類のアクションを定義しています。ClickとPointは、マウスのクリックとカーソル座標を取得するPC用の設定です。Tapが、Touchscreenを最初にタッチしたPrimary Touchを取得するスマホ用の設定です。
ここで問題となるのが、スマホのWebブラウザーでは、TouchscreenのPositionは取得できるのですが、タッチ操作に対応していないようなのです。あれこれ調べてみると、Pointerで対応できるということでした。ということで、その方向で対応させます。
アクションごとの設定
アクションごとのAction TypeやInitial State Checkの設定は、次のとおりです。
- Click
- Action Type: Pass Through
- Initial State Check: false
- Point
- Action Type: Pass Through
- Initial State Check: true
- Tap
- Action Type: Pass Through
- Initial State Check: false
Pass Throughってなんだっけという場合に備え(そうなった)、こちらの記事にしました。
Clickは、マウスがクリックされるか、WebGLの画面がタップされた時のperformedを使っています。startedやcanceledは使いません。また、マウスと画面タップの違いは気にしないので、最後に操作された入力が得られるPassThroughにしました。開始時に操作されているものは無視したいので、Initial State Checkは無効にしています。
Pointは、マウスの座標の読み取りのためのアクションです。マウスの座標は、デフォルト値が操作に影響せず、startedとcanceledの意味がありません。そのため、処理が軽いPassThroughを選択しました。Initial State Checkを有効にしているのは、開始時のマウス座標を報告してもらうためです。これにより、シーンが切り替わった直後のマウスの座標が取得できるので、最初からマウスカーソルを表示できます。
Tapの設定は、タッチスクリーンのみバインドしています。startedとcanceledは使っていないので、処理が軽いPassThroughにしました。有効になった時点でタッチしていても無効にしたいので、Initial State Checkは無効にしました。
解決策
あれこれ調査した結果、次の2手で解決できました。
- InputActionのClickに、PointerのPressを追加する
- 座標は、クリックやプレスを検出したときに、PointerのPositionを取得する
修正したInputAction
InputActionに、次のようにPointerのPressを追加しました。

これで、タッチに反応するようにはなります。しかし、タップ座標がズレるという問題が起きます。座標の取得方法の改良が必要です。
タップ座標を取得する
座標の取得は、マウスとタッチで性質が異なります。マウスの場合、クリックをしていなくても、マウスカーソルの位置をPointアクションで受け取れます。その値を記録しておけば、クリックした座標として使えます。
ところが、Pointerの場合は、pressされるまで座標は分かりません。Pointアクションにpositionをバインドしていても、Clickアクションの時点では、その座標はまだ受け取れていません。そのため、マウスと同じ実装だと、前回にタッチした座標をタッチしたことになってしまいます。
これを解決するために、クリック時に、Pointerデバイスの座標を読み取って、現在の座標として使うことにしました。Clickアクションに登録するメソッドは、次のような感じです。
void OnClickPerformed(InputAction.CallbackContext context) { if (context.ReadValueAsButton()) { // 座標を更新 currentPoint = Pointer.current.position.ReadValue(); // クリック処理のユーザーメソッドの呼び出し Action(currentPoint); } }
まず、context.ReadValueAsButton()で、クリックした時であることを確認しています。ClickアクションはPass Throughなので、離した時にもperformedが呼び出されます。このif文で、離した処理を無視します。
Pointer.current.position.ReadValue()で、現在のPointerの座標を読み取って、マウスの現在の座標を代入しているcurrentPointに代入しています。
あとは、currentPointに対して行動させるためのユーザーメソッドであるAction(currentPoint)を呼び出しています。
InputActionのPointに、Pointer用の座標アクションを追加しなかったのは、このように座標をPress時に直に読み取るので、Pointer用の座標アクションが不要だからです。
以上で、対応が完了できました。
まとめ
UnityのWebGLビルドは優秀なので、スマホのWebブラウザー上でも、かなりしっかりと動作します。ただ、InputSystemの扱いがスマホと異なるため、対応が必要でした。
スマホのWebブラウザーでは、タッチ操作をPointerとして認識するので、Pointerの操作をバインドしました。今回は、タッチした座標が必要なだけなので、Clickアクションに、PointerのPressをバインドしました。座標は、Clickアクション内で、引数から読み取るようにしました。これで、サンプルゲームを、スマホでも遊べるようになりました。
この記事は、Unity - Qiita Advent Calendar 2025 - Qiitaのシリーズ2の4日目の記事でした。
- 前の日は、tsubaki_t1 - QiitaさんのUtility AIです。
- 次の日は、nattoufu - Qiitaさんの音ゲーを創る[基本実装編]です。