質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

3064閲覧

[Unity] KeyCode.Backslashで、2つのキーが検出される。

regonili

総合スコア6

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/10/15 09:22

前提・実現したいこと

Unityで装飾キーやテンキーなど以外のキーを すべて個別に取得したい。
KeyCodeを使わなくても構わない。実装できれば何でも良い。
(欲を言えば管理するキーの数が多いから まとめて管理ができれば楽)

発生している問題

(日本語配列のキーボードで)
バックスラッシュを取得しようとしたとき、
KeyCode.Backslashで取得しようとすると、
バックスペースの隣と右シフトの隣のどちらもが反応する。

試したこと

(コード引用)

C#

1using System; 2using System.Linq; 3using UnityEngine; 4 5public class KeycodeTest : MonoBehaviour { //※クラス名は任意 6 7 KeyCode[] keyCodes = Enum.GetValues(typeof(KeyCode)).Cast<KeyCode>().ToArray(); 8 9 // Update is called once per frame 10 private void Update () { 11 if (Input.anyKeyDown) //※KeyDown のみ 12 { 13 foreach (var key in keyCodes) 14 { 15 if (Input.GetKeyDown(key)) 16 { 17 Debug.Log(key); 18 break; 19 } 20 } 21 } 22 } 23}

のように 取得したキーコードを表示させても どちらもがBackslashだった。
(ネットで調べたが 自分の検索力では解決しなかった。)

補足情報

  • Unity 2020.1.9f1 (常に最新版を使う予定)
  • Windows 10
  • JISキーボード

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

検証不十分な意見で申しわけないのですが、もしかすると右シフトキー隣のバックスラッシュはファンクションキー扱いになっているかもしれません。
下記のようなコードで円記号キーとバックスラッシュキーの違いがあるでしょうか?

C#

1using UnityEngine; 2 3public class BackslashTest : MonoBehaviour 4{ 5 private bool needsCheckBackslash; 6 7 private void Update() 8 { 9 this.needsCheckBackslash |= Input.GetKeyDown(KeyCode.Backslash); 10 } 11 12 private void OnGUI() 13 { 14 if (this.needsCheckBackslash) 15 { 16 var e = Event.current; 17 if (e.isKey) 18 { 19 if (e.functionKey) 20 { 21 Debug.Log("Backslash"); 22 } 23 else 24 { 25 Debug.Log("Yen"); 26 } 27 28 this.needsCheckBackslash = false; 29 } 30 } 31 } 32}

私の場合は区別できたように見えたのですが、はたしてどの環境でも通用するのかはすごく不確かです。すみません...

##追記

下記のようにもっと詳しい情報を出力させるようにしたバージョンを試してみたところ...

C#

1using UnityEngine; 2 3public class BackslashTest2 : MonoBehaviour 4{ 5 private bool needsCheckBackslash; 6 7 private void Update() 8 { 9 if (Input.GetKeyDown(KeyCode.Backslash)) 10 { 11 this.needsCheckBackslash = true; 12 Debug.Log($"Update frame: {Time.frameCount}"); 13 } 14 } 15 16 private void OnGUI() 17 { 18 if (this.needsCheckBackslash) 19 { 20 var e = Event.current; 21 Debug.Log($"OnGUI frame: {Time.frameCount}, Event type: {e.type}"); 22 if (e.isKey) 23 { 24 if (e.functionKey) 25 { 26 Debug.Log("Backslash"); 27 } 28 else 29 { 30 Debug.Log("Yen"); 31 } 32 33 this.needsCheckBackslash = false; 34 } 35 } 36 } 37}

ご質問者さんのご指摘通り、KeyDownを見逃してKeyUp時点で反応していたようでした。

図

どうやら「Updateでキーダウンがあったかを判断し、その後のOnGUIで円記号かバックスラッシュか判定する」というのでは遅すぎたようです。全部OnGUI内で完結させるよりないかもしれません。

C#

1using UnityEngine; 2 3public class BackslashTest3 : MonoBehaviour 4{ 5 private void OnGUI() 6 { 7 var e = Event.current; 8 if (e.type == EventType.KeyDown) 9 { 10 // https://docs.unity3d.com/ja/current/ScriptReference/EventType.KeyDown.html によると 11 // キーを押した時にはkeyCodeを持つイベントとcharacterを持つイベントが別々に発行されるらしい 12 if (e.keyCode == KeyCode.None) 13 { 14 Debug.Log($"Character: [{e.character}]"); 15 } 16 else if (e.keyCode == KeyCode.Backslash) 17 { 18 if (e.functionKey) 19 { 20 Debug.Log("Backslash"); 21 } 22 else 23 { 24 Debug.Log("Yen"); 25 } 26 } 27 else 28 { 29 Debug.Log(e.keyCode); 30 } 31 } 32 } 33}

##さらに追記

他にも、OnGUIに頼らずそれぞれのキーを識別できそうな可能性として...

  • パッケージマネージャーでInput Systemをインストールし、「Edit」→「Project Settings...」の「Player」→「Other Settings」→「Configulation」→「Active Input Handling*」を「Both」にして旧来のInputとInput Systemが同時に動作するようにしておく。
  • 大部分のキーの識別は従来通りUpdate内などでInputを使って行う。
  • Inputによる判定でKeyCode.Backslashが出てきた時にInput Systemによる追加判定を行う。

という手が使えるかもしれません。Input単独で両方のキーを識別する手段がどうにも見つからず、Input Systemならどうかと思って見てみたところ、どうやらこちらはバックスラッシュキーでoem2Keyが反応するようでした。
ですが円記号キーでは無反応(どのキーコントロールにも反応がない?)のような挙動をしていましたので、Input System単独でも厳しいかもしれません。そこで両方を折衷してみました。

C#

1using System; 2using System.Linq; 3using UnityEngine; 4using UnityEngine.InputSystem; 5 6public class BackslashTest4 : MonoBehaviour 7{ 8 private readonly KeyCode[] keyCodes = Enum.GetValues(typeof(KeyCode)).Cast<KeyCode>().ToArray(); 9 10 private void Update() 11 { 12 // 何らかのキーが押し下げられたら... 13 if (Input.anyKeyDown) 14 { 15 // すべてのキーを走査して... 16 foreach (var key in keyCodes) 17 { 18 // キーダウンがあったかを調べ... 19 if (Input.GetKeyDown(key)) 20 { 21 if (key == KeyCode.Backslash) 22 { 23 // キーコードがBackslashの時は、さらにOEM2キーに反応があるかを調べる 24 if (Keyboard.current.oem2Key.wasPressedThisFrame) 25 { 26 // 反応があれば右シフト隣のバックスラッシュ 27 Debug.Log("Backslash"); 28 } 29 else 30 { 31 // 反応がなければバックスペース隣の円記号 32 Debug.Log("Yen"); 33 } 34 } 35 else 36 { 37 // バックスラッシュ以外はそのまま表示 38 Debug.Log(key); 39 } 40 41 break; 42 } 43 } 44 } 45 } 46}

投稿2020/10/17 14:37

編集2020/10/21 01:46
Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

regonili

2020/10/20 11:35 編集

解答ありがとうございます! 間違いなく私の環境でも区別してくれたのですが、解答頂いたコードを実行してみると、 needsCheckBackslash が true になるタイミングが、キーを離した瞬間 または しばらく長押ししたら になりませんか…?私の環境だとそうなったんですけど、なんでですかね… (それとコードをいじってて疑問に思ったんですけど、(右シフト隣のキーの) functionKey が true になるタイミングはキーを離した瞬間?みたいな謎仕様なんですか…?)
regonili

2020/10/20 11:10

if(e.isKey)を削除すると即座に反応するようになりました(代わりにfunctionKeyを判別しなくなりました)。
Bongo

2020/10/20 14:30

ご指摘ありがとうございます。さらに調査してみた結果を追記しました。 なお、if (e.isKey)の条件分岐を削除した時に反応しなくなった件についてですが、OnGUIは追記しましたスクリーンショットにあるようにキーボード以外にもいろいろなイベントで作動しますので、おそらくLayoutやらrepaintやらに誤反応してしまったんじゃないかと思います。
regonili

2020/10/21 10:00

ありがとうございます!無事に出来ました! 全体的に返答が遅くなって申し訳ありません…
guest

0

今更ですが別の方法を思いついたので書きます。
GetKeyState
キーコード
Windows10x64でのみ動作確認
Win32 APIを使用しているからWindows OS以外では動かないでしょう。(未確認)

C#

1using System.Runtime.InteropServices; //DllImportに必要 2using UnityEngine; 3 4public class \ファイル名と同じに\ : MonoBehaviour 5{ 6 //キーボードの上下を見る Win32 API 7 [DllImport("user32.dll")] 8 private static extern short GetKeyState(int nVirtKey);//(GetAsyncKeyStateでも可) 9 10 void Update() 11 { 12 //GetKeyState(キーコード) < 0 なら押されている 13 //押された瞬間とかは自作しないとだめだと思う 14 if(GetKeyState(0xDC) < 0) Debug.Log("\\|キー"); //VK_OEM_5キー 15 if(GetKeyState(0xE2) < 0) Debug.Log("\\_キー"); //VK_OEM_102キー 16 } 17}

投稿2022/03/05 10:15

regonili

総合スコア6

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問