91939


windows環境限定での話になりますが、Unityの3Dゲームの開発中に発生したユーザー操作による不具合の再現性を高めるためにいくつかの方法で操作ログをもとにユーザーのPC操作を再現するツールを開発or捜索しております。

操作再現に必要な条件：

  * Unity側のプログラムの設定としてマウスカーソルの実体座標が移動できないようにロックを行っています。  
※[Unityカーソル制御について](https://miyagame.net/cursor-expression-nonindicating/)

  * マウスのクリック/移動量/ポインタの座標/キーボード入力などの事前に記録したログを再現できるようなプログラムを開発可能か
  * 開発したユーザー操作再現のスクリプトで実際にマウス操作（ポインタ移動/クリック/ドラッグ）とキーボード操作がUnity側へ正常に反映できるか

以上のような要件で評価しています。

python以外の方法も模索しており、有力候補として有償ソフトウェアのMacro
Recorderなどを運用する方法も検討しておりますが、内製ができる可能性の調査としてpythonを含む複数の言語で調べています。

pythonに関して  
PyAutoGUIを試しましたが、マウスの移動量を再現するMove/MoveTo系を試験したところ、Unity側でマウス実体座標が固定されていることに起因すると思われる移動操作の失敗（Unity側の画面にマウス操作が反映されていない）を確認しました。

クリックやキーボード操作系はすでに動作することが確認できており問題ありませんが、マウス移動プログラムだけはpython内で実現できない可能性が出てきました。

そこでpython3系でマウス移動を制御できるライブラリもしくはプログラムを探しており、以下の種類を発見しました。

発見済みのライブラリ：

[code]

    #1
    import mouse
    mouse.move("500", "500")
    #※https://github.com/boppreh/mouse#api
    
    #2
    import win32api
    pos = (200, 200)
    win32api.SetCursorPos(pos)
    
[/code]

まだ試験開発の途中でPyAutoGUI以外のこの2種の評価が済んでおりませんが、  
もし他にライブラリなどございましたら教えていただけますでしょうか。

2022/10/26追記：  
追加で発見した資料を追記していきます。  
[DirectX等ゲーム用環境上でPyAutoGUIが機能しないことについて](https://www.learncodebygaming.com/blog/pyautogui-
not-working-use-directinput)  
[ライブラリPyDirectInput](https://pypi.org/project/PyDirectInput/)


CC BY-SA 4.0
2022-10-26T02:54:30.577
91829
2022-11-02T02:18:20.600
2022-11-02T02:18:20.600
3060
51823
question
python python3 windows
Python3系でマウスを制御することができるライブラリは他にありますか


複数の代案を調べた結果、win32apiなどのライブラリではDirectX環境のマウスポインタの制御が厳しいことがわかりました。

以下は新しく見つけたSendInput系の制御方法による作例です。  
こちらはDirectX上のマウスポインタも正常に制御できる事がわかりました。  
こちらの情報に関する引用記事は[こちら](https://qiita.com/safin/items/09e41718f60d126aa99d)

以下のライブラリによるpythonによるマウス制御方法が存在することも確認しております。  
・win32api ※最新バージョンライブラリではpyinstallerでexe化すると動作しないので旧バージョンを使用する前提  
・pyautogui  
・mouse  
・autopy  
・pydirectinput

ただし、SendInput以外の制御方法では正常に制御できなかったので現状最強のマウスポインタ制御コードになるかなと思われます。

[code]

    import time
    import ctypes
    ULONG_PTR = ctypes.POINTER(ctypes.c_ulong)
    
    # マウスイベントの情報
    class MOUSEINPUT(ctypes.Structure):
        _fields_ = [("dx", ctypes.c_long),
                    ("dy", ctypes.c_long),
                    ("mouseData", ctypes.c_ulong),
                    ("dwFlags", ctypes.c_ulong),
                    ("time", ctypes.c_ulong),
                    ("dwExtraInfo", ULONG_PTR)]
    
    
    class CTYPESINPUT(ctypes.Structure):
        _fields_ = [("type", ctypes.c_ulong),
                    ("mi", MOUSEINPUT)]
    
    #マウス制御初期化諸々
    LPINPUT = ctypes.POINTER(CTYPESINPUT)
    SendInput = ctypes.windll.user32.SendInput
    SendInput.argtypes = (ctypes.c_uint, LPINPUT, ctypes.c_int)
    SendInput.restype = ctypes.c_uint
    
    #座標指定
    
    for i in range(800):
        x, y = i, i
        x = x * 65536 // 1920
        y = y * 65536 // 1080
        # MOUSEINPUT(x座標, y座標, ホイールの回転量, マウスイベント, 0, None)
        _mi = MOUSEINPUT(x, y, 0, (0x0001 | 0x8000), 0, None)
        # SendInput(1, CTYPESINPUT(入力の種類, _mi), ctypes.sizeof(CTYPESINPUT))
        SendInput(1, CTYPESINPUT(0, _mi), ctypes.sizeof(CTYPESINPUT))
        time.sleep(0.0001)
    
[/code]

なお、PyAutoGUIライブラリも上記と同様の処理を経由していることがわかりました。  
ただし、私の掲載する「_mi = MOUSEINPUT(x, y, 0, (0x0001 | 0x8000), 0,
None)」の部分がPyAutoGUIでは省略した書式で入力されているようでしたのでおそらくこれが原因で正常に動作しなかったものと考えられます。


CC BY-SA 4.0
2022-11-02T01:51:25.683
91939
2022-11-02T02:05:52.707
2022-11-02T02:05:52.707
51823
51823
91829
answer