[Unity, InputSystem] 仮想マウスの実装で詰まった点
背景
現在 Unity で制作中のゲームでコントローラーからマウスを動かすために仮想マウスを実装する際に、日本語の情報があまり存在せず詰まってしまったので、問題点と解決方法を共有します。
基本的な仮想マウスの実装方法
InputSystem はVirtualMouseInput
というクラスを提供しており、VirtualMouse
コンポーネントを任意のオブジェクトにアタッチし、いくつかの設定をすることで簡単に仮想マウスを実装することができます。
基本的な仮想マウスの実装方法は以下の記事を参考にするのがいいと思います。
VirtualMouseInput の問題点
上の記事でも触れられていますが、公式が提供しているVirtualMouseInput
クラスには以下のような問題点があります。
-
CanvasScaler
のUI Scale Mode
がConstant Pixel
以外の場合、仮想マウスの位置が正しく表示されない。 -
仮想マウスの有効/無効化が行えない。
-
InputAction
のActionType
をPassThrough
にする必要がある。
問題点の解決方法
CanvasScaler
のUI Scale Mode
がConstant Pixel
以外の場合、仮想マウスの位置が正しく表示されない。
1. この点はUnity のフォーラムでも議論されていた内容で、VirtualMouseInput
内の座標を更新する部分を修正する必要があります。
以下に変更点を示します。
@@ class VirtualMouseInput : MonoBehaviour
private void UpdateMotion()
{
+ // キャンバスを取得できていない場合はキャンバスを探す
+ if (m_Canvas == null)
+ TryFindCanvas();
if (m_VirtualMouse == null)
return;
@@ private void UpdateMotion()
// Update software cursor transform, if any.
if (m_CursorTransform != null &&
(m_CursorMode == CursorMode.SoftwareCursor ||
(m_CursorMode == CursorMode.HardwareCursorIfAvailable && m_SystemMouse == null)))
- m_CursorTransform.position = newPosition;
+ {
+ // 仮想マウスのスクリーン座標をキャンバスのローカル座標に変換
+ Vector2 localPos;
+ RectTransformUtility.ScreenPointToLocalPointInRectangle(
+ m_CursorTransform.parent as RectTransform,
+ newPosition,
+ m_Canvas.worldCamera,
+ out localPos);
+ m_CursorTransform.anchoredPosition = localPos;
+ }
また、この記事の最後に、私が実際に使用しているMyVirtualMouseInput
クラスのコードを載せておきますので、参考にしてください。
2. 仮想マウスの有効/無効化が行えない。
この点も Unity のフォーラムで議論されていた内容で、色々なアプローチがあるようですが、いくつかの方法を試してもクリックやマウスホバーの判定が残ってしまっていました。
私は、VirtualMouseInput
にisActive
というフィールドを追加し、isActive
がfalse
の時は仮想マウスの座標を-9999, -9999
に固定するようにしました。
以下に変更点を示します。
@@ class VirtualMouseInput : MonoBehaviour
+ public bool isActive = true;
@@ class VirtualMouseInput : MonoBehaviour
private void UpdateMotion()
{
+ // 無効状態なら画面外に固定して早期リターンする
+ if (!isActive)
+ {
+ Vector2 offScreenPos = new Vector2(-9999, -9999);
+ InputState.Change(m_VirtualMouse.position, offScreenPos);
+ if (m_CursorTransform != null)
+ m_CursorTransform.anchoredPosition = offScreenPos;
+ return;
+ }
実際に使用する際は、VirtualMouseInput
のisActive
と、設定しているImage
コンポーネントの表示/非表示を切り替えることで仮想マウスの有効/無効化を行うことができます。
InputAction
のActionType
をPassThrough
にする必要がある。
3. これは私の単純な確認不足で、VirtualMouseInput
に渡すInputAction
のActionType
をPassThrough
にする必要があるようでした。
実際に、InputSystem
を追加した際に自動生成されるInputActionAsset
内の UI 関連のActionType
はPassThrough
になっていました。(新しいInputAction
を作成するとValue
になりますが)
この点の確認不足で仮想マウスをうまく動かすことができなかったので、困っている方は確認してみてください。
MyVirtualMouseInput の内容
以下が私が実際に使用しているMyVirtualMouseInput
クラスのコードです。
このクラスを任意のオブジェクトにアタッチし、通常のVirtualMouseInput
と同じように設定して下さい。
Discussion