読者です 読者をやめる 読者になる 読者になる

GameProgrammar's Night

ゲームプログラム系の覚え書き

UnrealEngine4用プラグイン DirectInputPadPluginの使い方

 UE4(Windows)でDirectInputゲームパッドを使えるようにするプラグインを作りました。

github.com

 DirectInputPadPlugin Ver.0.9のものです。
 これ以降、DirectInputゲームパッドのことをDIパッド(DIPad)、XInputのゲームパッドのことをXIパッド(XIPad)、両方合わせた場合はたんにゲームパッド(GamePad)と表記します。

インストール

  1. 上のGithubからソースをチェックアウト、もしくはZIPをDOWNLOADします。
  2. それらのソースを「DirectInputPadPlugin」という名前のフォルダを作って、そこに入れます
  3. 「DirectInputPadPlugin」フォルダを、[プロジェクトフォルダ]/Plugins に移動します

あとは、

katze.hatenablog.jp

を参考にソースをビルドしてください。

DirectInputゲームパッドの接続確認

 ゲームパッドをPCに挿した状態でUE4エディタを立ち上げます。動的な抜き差しには対応していませんので、エディタやゲーム起動前には挿しておいてください。
 接続が成功していれば、アウトプットログに

DirectInputPadPlugin: DirectInputDriver initialized.
DirectInputPadPlugin: DirectInputPad detected: 1
DirectInputPadPlugin: DirectInput Joystick Create Success. : Elecom Wired Gamepad

 見つかったDIパッドの数と、その数だけ接続が確認できたDIPadの名前が表示されます。
 これでDIパッドを使用する準備が完了です。

キーイベント

 GamePadイベントをそのまま使うことができます。

f:id:katze_7514:20151127232235j:plain

など。
 基本的には、GamePadイベントを使うことを想定しています。なぜなら、GamePadイベントはXIパッドのイベントでもありますので、ユーザーがXIパッドでもDIパッドでもどちらのゲームパッドを使っていても良くなるからです。

DIPadイベント

 DIパッドとして直接イベントを取ることもできます。こちらの場合だと、プラグインが対応してる最大限のキーイベントを取得することができます。

  • 6つの軸(XYZ軸、XYZ回転軸)
  • 1つのPOV
  • 32個のボタン(XIパッドは個数にすると12個まで)

 DIGamePadで始まる名前にしてあります。

f:id:katze_7514:20151127234617j:plain

 こちらは、DIパッドのボタン配置をXIパッドに合わせるキーコンフィグや、通常のゲームパッドではないDirectInputの入力デバイスを使う時に使います。

パッドキャリブレーション

 GamePadイベントをDIパッドでも使うには、DIパッドをXIパッドの配置にする必要があります。XIパッドというのは、ようはXBOXのパッドのことです。
 デフォルトでは以下のような対応になっています。

XIパッド DIパッド
左スティックX X軸
左スティックY Y軸
右スティックX Z軸
右スティックY Z回転軸
方向パッド上 POV上
方向パッド右 POV右
方向パッド下 POV下
方向パッド左 POV左
A ボタン1
B ボタン2
X ボタン3
Y ボタン4
LB(L1) ボタン5
RB(R1) ボタン6
Lトリガー(L2) ボタン7
Rトリガー(R2) ボタン8
BACK ボタン9
START ボタン10
左スティックボタン ボタン11
右スティックボタン ボタン12

 変更に使うノードは、SetKeyMapです。

f:id:katze_7514:20160827132842p:plain

 Ver.0.9からの機能として、軸にボタン、ボタンに軸を割り当てられるなど、キャリブレーションの自由度を上げました。
 図の左から

  • 「XIパッドの左スティックX軸として、DIパッドのX軸を割り当てる」
  • 「XIパッドの右スティックY軸(下方向)として、DIパッドのボタン1を割り当てる」
    • ボタン1が押されていないなら0,ボタン1が押されていると-1 が返るようになります
    • 上方向に割り当てる時は、Negativeフラグをオフにします
  • 「XIパッドのボタンAとして、DIパッドのX回転(正方向)を割り当てる」
    • X回転の正方向の値に応じて、ボタンAが押されているという判定がされます
    • X回転の負方向の値を使うならば、Negativeをオンにします

 Ver.0.8では対応できていなかったLT(L2)/RT(R2)への軸の割り当てもできるようになっています。

 SetKeyMapは重複してキーを割り当てられるのでご注意ください。KeyMapを削除するには、DIKeyの項目を「DIGamePad END」にすることでできます。

GetDirectInputPadJoystickノード

 PlayerIndexを使ってDIパッドを取得するノードです。DIパッドは見つかった順番にPlayerIndexが割り当てられて、対応するプレイヤーの入力として使われます。
 XIパッドが同時に挿しこまれていた場合は、XIパッドを優先します。DIパッドにはXIパッドの次のPlayerIndexが割り当てられます。つまり、XIパッドが挿しこまれてないないなら0番から、XIパッドが1つ挿しこまれていたら1番から割り当てられます。
 PlayerIndexに対応するDIパッドがなかった場合は、nullが返ります。

f:id:katze_7514:20160827133534p:plain

(回転)軸の反転

 DIパッドによっては、XIパッドと軸の値が逆になっていることがあります。XIパッドの左スティックYは上がプラスで下がマイナスになりますが、私が普段使っているDIパッドのY軸は上がマイナスで下がプラスになっています。
 このまま軸を割り当てると上下が反転した状態で処理されてしまいますので、軸の値を反転させる必要があります。その時は、SetAxisReverseノードを使います。

f:id:katze_7514:20151128012340j:plain

 引数上ではボタンも選べますが、当然意味はありません。
 反転フラグの値を調べるには、IsAxisReverseノードを使います。

ChangedState系ノード

 パッドキャリブレーションをサポートするノード群です。
 呼び出したフレームで状態に変化のあったキー情報を取得するノードです。
 状態の変化とは、軸なら初期値(通常は0)以外の入力値になっている、ボタンなら押されたか離されされたか、ということになります。

IsChangedKeyStateノード

f:id:katze_7514:20160827133734p:plain

 状態が変化したキーがあるかをチェックします。変化したキーがあればtrueが返ります。

Get(All)ChangedKeyStateノード

 
f:id:katze_7514:20160827134033p:plain

 GetChangedKeyStateノードは変化のあったキー1つだけ、GetAllChangedKeyStateは変化のあったキーすべて取得します。
 変化のあったDIパッドとしてのenumと変化値が取得できます。変化値は、軸の時は軸の値、ボタンの時は正だとPressed、負だとReleasedの意味になります。

 Real引数をtrueにすると、反転フラグなどキー設定を無視したパッドの実入力値で変化値を取得できます。

 GetChangedKeyStateは、通常は軸の変化を優先しますが、Btn引数をtrueにすることでボタンの変化を優先的に取得するようになります。

 ユーザーに「Aボタンの場所を押してください」などと促し、押されたボタンを検出(GetChangeKeyState)、そのボタンをAボタンとして設定する(SetKeyMap)、という使い方を想定しています。

キャリブレーションのセーブロード

f:id:katze_7514:20160827134219p:plain

 図のノードを使うことで、現在接続されているDIパッドに設定されたキャリブレーションデータ(KeyMap)をセーブロードすることができます。引数の意味は、SaveGameToSlot/LoadGameFromSlotと同じです。

ユーティリティー

ゲームパッドの数

 挿しこまれている各ゲームパッドの数は、次のノードで取得できます。
 取得できなかったの時は、-1が返ります。

f:id:katze_7514:20151128011543j:plain

ゲームパッドの名前と識別子

 ゲームパッドの名前はGetProductNameノード、識別子はGetGUIDノードで取得できます。

f:id:katze_7514:20151202181513j:plain

 名前はまったく同じパッドの場合、同じ名前になることがあるので識別には使えませんが、ユーザーがコントロールしているパッドを示すのには使えます。
 キーコンフィグ情報を保存/復元する際など、個々のパッドを識別するためにはGUIDを使用してください。ただし、このGUIDはローカルでのみ一意性が保証されてるGUIDですのでご注意ください。

入力値のクリア

 現在保持している入力値をクリアします。

f:id:katze_7514:20151213183116j:plain

プラグインが初期化できたか

f:id:katze_7514:20160220040421p:plain

コンフィグ

BACKGROUND設定にするか

DefaultInput.ini に以下のセクションを追加してください

[DirectInputPadPlugin]
Background=true

エディタ起動時は、常にBACKGROUND動作となります。

以上になります。

使用上の注意

 タイミングよっては、最初にロードされるLevelのBeginPlayにプラグインの初期化が間に合わないことがあります。その場合は、各APIが正しい値を返せません。プラグインの初期化を待ってからAPIを呼ぶようにしてください。

質問とか

 プラグインの使い方で、質問とかありましたら、この記事のコメントか、Twitterでリプを投げてください。
 バグがあったらプルリクお待ちしてます!