![見出し画像](https://assets.st-note.com/production/uploads/images/124615840/rectangle_large_type_2_6be033d8241b05b696e97bead3db9a70.png?width=1200)
NDI™で送信するRTAイベントタイマーをUnityで作る #04 キーボード入力編
前回、コントローラーでストップウォッチが動いたので今度はキーボードで動かしましょう。イベントでは技術担当が操作するイメージです
誤操作防止
イベント中はパソコンを他の用途にも使いたいので、キーボードでの操作はCtrl キーや Alt キーを同時押ししないと動かないようにします。さらに、通常操作できない F13~F24 キーを割り当てて、どうやっても誤操作がおきないようにします
KeyboardInput.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
public class KeyboardInput : MonoBehaviour
{
[DllImport("user32.dll")]
static extern bool GetKeyboardState(byte[] lpKeyState);
const int VK_F13 = 0x7C;
const int VK_F14 = 0x7D;
const int VK_F15 = 0x7E;
const int VK_F16 = 0x7F;
const int VK_F17 = 0x80;
const int VK_F18 = 0x81;
const int VK_F19 = 0x82;
const int VK_F20 = 0x83;
const int VK_F21 = 0x84;
const int VK_F22 = 0x85;
const int VK_F23 = 0x86;
const int VK_F24 = 0x87;
const int VK_LCONTROL = 0xA2;
const int VK_RSHIFT = 0xA1;
const int VK_RMENU = 0xA5;
private byte[] old_key = null;
[SerializeField] CountUpMain countup;
// Start is called before the first frame update
void Start()
{
old_key = new byte[256];
GetKeyboardState(old_key);
}
// Update is called once per frame
void Update()
{
byte[] now_key = new byte[256];
GetKeyboardState(now_key);
if (countup != null)
{
if (isKeyDown(now_key, VK_LCONTROL) == true && isKeyDown(now_key, VK_RMENU) == true)
{
if (isKeyDown(now_key, VK_F13) == true && isKeyDown(old_key, VK_F13) == false)
{
countup.input_status = CountUpMain.InputStatus.start;
}
if (isKeyDown(now_key, VK_F14) == true && isKeyDown(old_key, VK_F14) == false)
{
countup.input_status = CountUpMain.InputStatus.stop;
}
if (isKeyDown(now_key, VK_F15) == true && isKeyDown(old_key, VK_F15) == false)
{
countup.input_status = CountUpMain.InputStatus.pause;
}
if (isKeyDown(now_key, VK_F16) == true && isKeyDown(old_key, VK_F16) == false)
{
countup.input_status = CountUpMain.InputStatus.resume;
}
if (isKeyDown(now_key, VK_F17) == true && isKeyDown(old_key, VK_F17) == false)
{
countup.input_status = CountUpMain.InputStatus.reset;
}
}
if (isKeyDown(now_key, VK_LCONTROL) == true && isKeyDown(now_key, VK_RSHIFT) == true)
{
if (isKeyDown(now_key, VK_F13) == true && isKeyDown(old_key, VK_F13) == false)
{
countup.input_status = CountUpMain.InputStatus.up_1sec;
}
if (isKeyDown(now_key, VK_F14) == true && isKeyDown(old_key, VK_F14) == false)
{
countup.input_status = CountUpMain.InputStatus.down_1sec;
}
if (isKeyDown(now_key, VK_F15) == true && isKeyDown(old_key, VK_F15) == false)
{
countup.input_status = CountUpMain.InputStatus.up_10sec;
}
if (isKeyDown(now_key, VK_F16) == true && isKeyDown(old_key, VK_F16) == false)
{
countup.input_status = CountUpMain.InputStatus.down_10sec;
}
if (isKeyDown(now_key, VK_F17) == true && isKeyDown(old_key, VK_F17) == false)
{
countup.input_status = CountUpMain.InputStatus.up_1min;
}
if (isKeyDown(now_key, VK_F18) == true && isKeyDown(old_key, VK_F18) == false)
{
countup.input_status = CountUpMain.InputStatus.down_1min;
}
if (isKeyDown(now_key, VK_F19) == true && isKeyDown(old_key, VK_F19) == false)
{
countup.input_status = CountUpMain.InputStatus.up_10min;
}
if (isKeyDown(now_key, VK_F20) == true && isKeyDown(old_key, VK_F20) == false)
{
countup.input_status = CountUpMain.InputStatus.down_10min;
}
if (isKeyDown(now_key, VK_F21) == true && isKeyDown(old_key, VK_F21) == false)
{
countup.input_status = CountUpMain.InputStatus.up_1hour;
}
if (isKeyDown(now_key, VK_F22) == true && isKeyDown(old_key, VK_F22) == false)
{
countup.input_status = CountUpMain.InputStatus.down_1hour;
}
if (isKeyDown(now_key, VK_F23) == true && isKeyDown(old_key, VK_F23) == false)
{
// 割り当てなし
}
if (isKeyDown(now_key, VK_F24) == true && isKeyDown(old_key, VK_F24) == false)
{
countup.input_status = CountUpMain.InputStatus.updown_reset;
}
}
}
Array.Copy(now_key, old_key, 256);
}
bool isKeyDown(byte[] key, int code)
{
return ((key[code] & 0x80) != 0);
}
}
バックグラウンドで動作可能
タイマーを操作する瞬間に別の操作をしている可能性もあるので、ウィンドウにフォーカスがなくても動くようにします。他の方法だとうまく動かなかったので、一番シンプルに Win32 API からキーボードの状態を取得します
そのままだとキーボードを押したままなのか、押した瞬間なのかわからないので、1フレーム前の状態を保持しておき変化した場合のみ CountUpMain のinput_status プロパティを変更します
Stream Deck 使用
修飾キーの左右を判別できるため、ストップウォッチの場合は左 Ctrl キーに右の Alt か Shift を組み合わせて押し、その状態で F13~F24 を押した際にいろいろな動作をするようにします。普通のキーボードでは押せないので、ここでは Elgato の Stream Deck を使います。ホットキー入力を設定することにより、1ボタンで各操作ができるようになります。間違えて押してしまわないように、階層を深く設定しています
![](https://assets.st-note.com/img/1701421056120-JzNbXcQWAL.png?width=1200)
![](https://assets.st-note.com/img/1701420764784-dpYl2nHBH3.png?width=1200)
![](https://assets.st-note.com/img/1701421089993-fm9tpNZxnV.png?width=1200)
正しく動作することを確認します
おつかれさまでした
キーボード入力を作成しましたが、本番では走者&解説の方にスタート&ストップを任せるため、技術担当はリセット以外操作する必要がないことになります。マウスで操作ができたら要らないかもですね。
次はカウントダウンタイマーを作りましょう