【Unity】【C#】EventSystem を InputSystem 用に置き換えると、スクロールビュー等の移動が速過ぎる 
2020/11/19 Thu [edit]
InputSystem を導入すると、EventSystem に「Replace with InputSystemModule」というボタンが出てくるが、これを押すと、UI などのイベントが InputSystem での検出に置き換わる。

しかし、実験していて気づいたのだが、ScrollView や Dropdown などに使われている ScrollRect でのスクロールが (旧)InputManager から引き継いで使っていると、過剰に反応することがあるようだ。
調べてみたら、たまたま私が (旧)InputManager の Axes>Mouse ScrollWheel の Sensitivity をデフォルトの 0.1 のまま、それを基準として各スクロールビュー関連の UI の速度を調整していたため、(新)InputSystem での基準値 1.0 では速くなり過ぎるということだった(つまり簡単には、Input.GetAxis("Mouse ScrollWheel") ではホイールを1目盛回すと 0.1 が返ってくるが、Mouse.current.scroll.ReadValue() では 1.0 が返ってくるため、反応が異なる)。

InputSystem.UI 辺りを使えば、基準値を変えられそうな気もするが、プロジェクトによって基準値が異なるのも互換性が損なわれるので、いっそのこと、ScrollRect の設定を一気に置き換えたら良いんじゃないか?とやってみたら、上手くいった。
その便利ツールのスクリプト。
(※) Unity 2019.4.14f1 / Windows10(x64) で確認
●ヒエラルキー(シーン)の全ての ScrollRect.scrollSensitivity を編集するツール(エディタ拡張)
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
#if UNITY_EDITOR
using UnityEditor;
#endif
/// <summary>
/// ヒエラルキー(シーン)の全ての ScrollRect.scrollSensitivity を編集するツール
/// 2020/11/19 Fantom (Unity 2019.4)
/// http://fantom1x.blog130.fc2.com/blog-entry-388.html
///
/// (使い方)
/// 1. ヒエラルキーに適当な GameObject にこのスクリプトをアタッチ
/// 2. インスペクタで「Multiply」(元の値を乗算する値:デフォルト 0.1 = 元の値を 1/10 にする)
/// 3. [Scan and Edit] ボタンを押す
/// </summary>
public class ScrollSensitivityScanAndEditTool : MonoBehaviour
{
[Header("Edit Parameter")]
public float multiply = 0.1f; //元の値を乗算
}
#if UNITY_EDITOR
/// <summary>
/// ヒエラルキー(シーン)の全ての ScrollRect.scrollSensitivity を編集するツール(エディタ拡張)
/// 2020/11/19 Fantom (Unity 2019.4)
/// http://fantom1x.blog130.fc2.com/blog-entry-388.html
/// </summary>
[CustomEditor(typeof(ScrollSensitivityScanAndEditTool))]
public class ScrollSensitivityScanAndEditToolEditor : Editor
{
bool _isBusy;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (Application.isPlaying)
return;
EditorGUILayout.Space(15);
if (GUILayout.Button("Scan and Edit") && !_isBusy)
{
ScanAndEdit();
}
}
void ScanAndEdit()
{
Debug.Log("Start Scan");
_isBusy = true;
var obj = target as ScrollSensitivityScanAndEditTool;
var multiply = obj.multiply;
int cnt = 0;
var scrolls = GetComponentsAll<ScrollRect>(); //※以前の記事を参照
if (scrolls != null && scrolls.Length > 0)
{
foreach (var scroll in scrolls)
{
cnt++;
var tr = scroll.transform;
var path = GetFullPathName(tr); //※以前の記事を参照
var sens = scroll.scrollSensitivity;
var edited = sens * multiply;
Undo.RecordObject(scroll, "Scroll Sensitivity Edit");
scroll.scrollSensitivity = edited;
Debug.Log($"Edited : {sens} -> {edited} - {path}");
EditorUtility.SetDirty(scroll);
}
}
_isBusy = false;
Debug.Log($"Finish Scan : Count = {cnt}");
}
#region Static methods
//Transform 関連メソッド
//http://fantom1x.blog130.fc2.com/?tag=Transform
// 現在のシーンのルートにある Transform を全て取得 (非アクティブも含む)
// http://fantom1x.blog130.fc2.com/blog-entry-377.html
static Transform[] GetRootTransforms()
{
var scene = SceneManager.GetActiveScene();
var objects = scene.GetRootGameObjects();
return objects.Select(go => go.transform).ToArray(); //無い時は 0 個の配列(null にはならない)
}
// 現在のシーン(ヒエラルキー)の全てのオブジェクトからコンポーネントを取得する(非アクティブも含む)
// http://fantom1x.blog130.fc2.com/blog-entry-378.html
static T[] GetComponentsAll<T>()
{
var list = new List<T>();
var roots = GetRootTransforms(); //ルートにある Transform 全て取得(非アクティブも含む)
//全てのルート Transform 以下に GetComponentsInChildren() する
foreach (var tr in roots)
{
var objects = tr.GetComponentsInChildren<T>(true); //非アクティブも含む取得
if (objects != null && objects.Length > 0)
{
list.AddRange(objects);
}
}
return list.ToArray(); //無いときは、0 個の配列(null にはならない)
}
// Transform の(フル)パス名を作成する
// http://fantom1x.blog130.fc2.com/blog-entry-379.html
static string GetFullPathName(Transform transform)
{
if (transform.parent == null)
return transform.name;
return GetFullPathName(transform.parent) + "/" + transform.name;
}
#endregion Static methods
}
#endif
GetRootTransforms, GetComponentsAll, GetFullPathName の3つのメソッドは以前の記事を参照。
まぁ、実の事を言うと、以前に配布した AttachedImageFinder のコードを少し改造して、適当な GameObject にアタッチして、インスペクタで実行する形にしたものである。普通1度しか使わないだろうし、メニューにずっといるのも邪魔なので、使う時はヒエラルキーに置いて、使い終わったら削除する、みたいな方法で良いかな、と。
使い方は [Scan and Edit] ボタンを押すだけだが、インスペクタの設定は Multiply で「元の値×設定値」に更新するので、デフォルトは 1/10 倍(= 0.1) となっている。例えば、(旧)InputManager のとき ScrollRect の Sensitivity が 100 に設定されていたなら、実行後は 100 x 0.1 = 10 に更新されているハズだ。だいたいこれで (新)InputSystem でも同じ感覚になるようだ((旧)InputManager の "Mouse ScrollWheel" の Sensitivity が 0.1 のとき)。


ただ、私が試した所(掲載時点:InputSystem 1.0.0)、PC では問題ないが、Android では微妙に UI の反応が悪い気がする。これは ScrollRect というより、新しく置き換えた EventSystem が不安定(?) な感じがするからだ。というのも、スクロール以外にも、例えばボタンなども、押しても反応しなくなったり、しばらくしたら、反応が良くなったりすることが多々ある。
どこに書いてあったか忘れたが、確か InputSystem は Unity から独立したポーリング(スレッド)で動いていて、Unity の描画遅延などの影響を受けない、みたいなことが説明されていた。しかし普通に考えれば、スレッド間でデータをやりとりするには、受信タイミングを合わせる必要がある。Android ではそれが上手く行ってないのかも知れない。少し前に Android のバックキーのバグレポを Unity公式に出したが、この問題は確認できたので対応すると返信が来た。この挙動もスレッド間通信による、同期失敗の可能性がある。
まぁ、私の所見ではあるが、まだ InputSystem 1.0.0 は変換キー関連や、モバイルでの挙動など、怪しい部分がいくつかあるので、一気に InputSystem に移行するのはやめた方が良いだろう。当面は InputManager と共存(Edit>Player Settings>Other Settings>Active Input Handling で Both にする)して、少しずつ動作確認してから、移行した方が良いかも知れない。ただ、InputSystem は機種依存がある気がするので(バグレポを複数出したが、確認とれないというのもあった → しかし、私の環境では再現できる)、できる限り色々な機種や条件を変えて試してみた方が良い気がする。
(関連記事)
【Unity】ヒエラルキー(シーン)の Image, RawImage に使われている画像(Texture)を検出するエディタ拡張(ツール)
【Unity】【C#】シーン(ヒエラルキー)のルートにある Transform を全て取得する(非アクティブも含む)
【Unity】【C#】非アクティブも含めて、全ての GameObject からコンポーネントを取得する
【Unity】【C#】Transfrom (GameObject) のパス名を取得する
【Unity】InputSystem 対応 ピンチ操作ライブラリ (FantomPlugin 追加機能)
【Unity】InputSystem 対応 スワイプ(フリック) 操作ライブラリ (FantomPlugin 追加機能)
【Unity】InputSystem 対応 長押し操作ライブラリ (FantomPlugin 追加機能)
【Unity】InputSystem 対応 ダブル/トリプル(n回)クリック操作ライブラリ (FantomPlugin 追加機能)
【Unity】【C#】(旧)KeyCode と InputSystem.Key の対応
【Unity】【C#】InputSystem の Keyboard クラスと (旧)Input.GetKey の対応
【Unity】【C#】InputSystem の Mouse クラスと(旧)Input.GetMouseButton の対応
【Unity】【C#】InputSystem.Key をリアルタイムで調べる / Windows 日本語キーボードでの Key 一覧
【Unity】【C#】InputSystem でマウスのホイール(scroll)取得と (旧)Input との対応
【Unity】【C#】InputSystem.TouchPhase の IsActive(), IsEndedOrCanceled() [拡張メソッド] の具体値
【Unity】【C#】InputSystem の displayName や control path から Key (キーコード) を取得(変換)する
【Unity】【C#】InputSystem で Android のバックキーの isPressed がなぜか一定時間で false になる?
- 関連記事
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/388-90f5fcda
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |