[Unity Engine] 키보드 키와 의미 단위 키

nlime3141592·2022년 4월 16일
0
post-thumbnail

키 정의

사용자에게 보다 의미 있는 경험을 제공하려면 사용자에게 다양한 선택지를 주어야 합니다. 키보드 입력을 제공하는 것은, 사용자가 게임 속 기능을 편리하게 사용할 수 있도록 하고 사용자의 자유 의지대로 다양한 방식으로 프로그램을 사용하기 위해 꼭 필요한 기능이 되겠습니다.

상기한 이유로, 현재 프로젝트에는 키보드 키와 의미 단위 키를 정의하여 관리하고 있습니다.
사실, Unity Engine이 제공하는 Input Manager를 사용하면 되지만, 개인적으로 그닥 마음에 안 들어서 일부 기능만 취사선택해서 사용 중입니다.

현재 프로젝트에서는 키보드 키와 의미 단위 키를 아래와 같이 정의하고 있습니다.

키보드 키

키보드 키란, 실제 물리 키보드에 존재하는 키 집합을 의미합니다.

A~Z, a~z
키보드 0~9
키패드 0~9
F1~F12
등등...

의미 단위 키

의미 단위 키란, 프로그램이 가진 동작을 수행하는 키 집합을 의미합니다.

이동 키
점프 키
공격 키
인벤토리 키
등등..

키 집합 설정

키보드 키는 열거형 UnityEngine.KeyCode로 정의되어 있고, 열거형의 요소는 키보드 키를 포함하고 있습니다. 자세한 내용은 UnityEngine.KeyCode 공식 문서를 참조하세요.

의미 단위 키도 마찬가지로 열거형으로 관리하고 있습니다. 현재 프로젝트에는 의미 단위 키 열거형이 선언되어 있습니다.

enum KeyType : int
{
	None,
	MoveL, MoveR, // 좌, 우 이동
   	Sit, Jump, Dash, // 플레이어가 기본적으로 취할 수 있는 동작
	Skill1, Skill2, Skill3,
	Inventory, ESC,
	등등.. 필요한 키 세팅들
}

키 집합 간 관계 정의

키보드 키와 의미 단위 키를 설정했으면, 두 키 집합 간 관계를 정의해야 합니다. 이 관계는 여러분의 게임이 어떻게 구현되느냐에 따라 천차만별이 되겠죠.

키 집합 간 관계를 F라 정의하자. 키보드 키 집합 I, 의미 단위 키 집합 K에 대해 관계 F는 다음과 같다.

F: I → K

즉, 아래 관계 테이블을 만드는 것입니다.

// 방향키 조작을 위해
UnityEngine.KeyCode.LeftArrow = KeyType.MoveL
UnityEngine.KeyCode.RightArrow = KeyType.MoveR
UnityEngine.KeyCode.DownArrow = KeyType.Sit
UnityEngine.KeyCode.C = KeyType.Jump

// WASD 조작을 위해
UnityEngine.KeyCode.A = KeyType.MoveL
UnityEngine.KeyCode.D = KeyType.MoveR
UnityEngine.KeyCode.S = KeyType.Sit
UnityEngine.KeyCode.Space = KeyType.Jump

등등.. 키 집합 간 관계를 설정해준다.

키 입력 상태 저장을 위한 배열

키 집합 간 관계를 정의했으면, 실제 키 입력 정보를 저장할 공간을 마련해줘야 합니다. 현재 프로젝트에서는 1차원 boolean 배열 B를 만들어 관리하고 있습니다.

Unity Engine은 Input 클래스에서 Key Down, Key Up, Key Pressing을 감지할 수 있도록 함수를 제공하고 있습니다.

UnityEngine.Input.GetKeyDown(KeyCode)
UnityEngine.Input.GetKeyUp(KeyCode)
UnityEngine.Input.GetKey(KeyCode) // Pressing 상태 감지

현재 프로젝트에는 각 KeyCode별 Key Down, Key Up, Key Pressing을 모두 기록하기 위해서 입력 유형을 명시한 PressType 열거형을 만들어서 구분하고 있습니다. PressType 열거형의 원소 집합을 P라고 정의합니다.

enum PressType
{
	Down, Up, Pressing
}

결론적으로, 한 키당 3개씩의 boolean값을 갖게 됩니다.

따라서, 본 문단에 정의한 1차원 boolean 배열 B는 (키보드 키 집합 I의 원소의 갯수) * 3의 길이를 가지고 있습니다. 즉, boolean 배열은 아래와 같이 구성됩니다.

{ Input.GetKeyDown(KeyCode.A), Input.GetKeyUp(KeyCode.A), Input.GetKey(KeyCode.A), ... } : bool[]

본 문단의 결론은, 집합 I와 P를 이용해서 boolean 집합 B를 만들어내는 연산을 소개한 것입니다. 집합 I, P에 대해 함수 G를 정의하면 아래와 같습니다.

G: (I, P) → B

역관계의 다가성 문제 해결

우리는 F: I → K 집합과 G: (I, P) → B 집합을 얻었습니다. 그러나 실제로 사용자에게 노출될 집합은 K 입니다. 집합 B를 만들기 위해서는 Inverse F를 사용해야 하는 것이죠. 최종적으로는 아래 관계가 되겠죠.

G: (Inverse F, P) → B

그런데 Inverse F는 의미 단위 키 하나에 키보드 키 여러 개의 관계를 가집니다. 집합 K의 임의의 한 키가 집합 I에 속한 여러 개의 키와 관계가 있다는 것입니다. 이를 함수의 다가성이라고 합니다. 해결이 어려울 것 같지만 이 문제는 생각보다 쉽게 해결될 수 있습니다.

KeyType.Jump가 UnityEngine.KeyCode.Space와 UnityEngine.KeyCode.C와 관계를 갖는다고 가정합시다. 둘 중 하나만 입력되어도 기능이 작동하고, 둘 다 입력 되어도 기능이 작동합니다. 즉, 관계를 갖는 집합 I의 키들과 OR연산을 수행하는 것입니다.

실제 InputSystem의 Pseudo Code는 아래와 같습니다.

1. Inverse F의 입력 k∈K가 집합 I'={i|i∈I}를 출력한다.
2. 판단하고 싶은 입력 유형 p∈P 1개를 결정한다.
3. G: (I', p) → B를 수행한다.
	3-1. 집합 I'의 모든 원소 i에 대해, 입력 유형 p에 대해, 다음을 수행한다.
       	if, p == PressType.Down and Input.GetKeyDown(i) => return true;
        if, p == PressType.Up and Input.GetKeyUp(i) => return true;
        if, p == PressType.Pressing and Input.GetKey(i) => return true;
4. return false;
profile
646576656c6f706572

0개의 댓글