C# - GetAsnycKeyState() 기반 실시간 키 입력 처리

2025. 10. 14. 17:04·C#

콘솔의 기본적인 Console.ReadKey() 기반으로 입력을 받으면, OS의 연속키 입력 지연 때문에 입력이 느리고 답답하게 느껴진다.

이는 실시간 게임 같은 것에서는 조작감을 치명적으로 망쳐놓는 원인이 된다.

 

비슷한 현상을 Unity에서도 겪은 바 있기에, 이를 해결하고자 KeyDown / KeyUp을 이용한 인풋 시스템을 만들고자 했으나

C#에는 KeyUp 기능이 없다...!

 

없으면 직접 만들어야지 뭐...

 

 

결론부터 말하면 GetAsyncKeyState()라는 Win32 API가 제공하는 비동기 키 입력 감지 함수를 이용해 해결할 수 있다.

 


 

if (Console.KeyAvailable)
{
    var key = Console.ReadKey(true).Key;
    switch (key)
    {
        case ConsoleKey.LeftArrow: player.MoveLeft(); break;
        case ConsoleKey.RightArrow: player.MoveRight(); break;
    }
}

 

최초에는 기존 Console.ReadKey() 방식을 이용해 switch문으로 간단하게 실시간 입력을 처리했고, 위에서 언급한 키 입력 지연 현상을 겪었다.

 

 

이 문제를 해결하기 위해

Win32 API GetAsnycKetState를 이용해보자.

[DllImport("user32.dll")]
private static extern short GetAsyncKeyState(int vKey);

 

  • vKey: 가상 키 코드 (예: 0x25 = ←, 0x26 = ↑ 등) // 폰트 오류... 티스토리 왜 그러니?
  • 반환값의 의미:
    • 0x8000 비트: 현재 키가 눌려있는지 (KeyDown 상태)
    • 0x0001 비트: 직전에 눌린 적이 있는지 (KeyPressed 이벤트)

즉, 이 API를 이용하면 콘솔 프로그램에서도
게임 엔진처럼 KeyDown, KeyPressed, KeyUp을 구현할 수 있다

 

 

 

전체 코드는 아래와 같다.

 

using System;
using System.Runtime.InteropServices;

namespace WeaponMasterDefense
{
    public static class InputSystem
    {
        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(int vKey);

        public static void HandleInput(Player player)
        {
            if (IsKeyDown(ConsoleKey.Escape)) Program.SetPaused();

            if (IsKeyDown(ConsoleKey.LeftArrow)) player.MoveLeft();
            if (IsKeyDown(ConsoleKey.RightArrow)) player.MoveRight();
            if (IsKeyDown(ConsoleKey.UpArrow)) player.MoveUp();
            if (IsKeyDown(ConsoleKey.DownArrow)) player.MoveDown();

            if (IsKeyPressed(ConsoleKey.Q)) player.skills[0].Activate(player);
            if (IsKeyPressed(ConsoleKey.W)) player.skills[1].Activate(player);
            if (IsKeyPressed(ConsoleKey.E)) player.skills[2].Activate(player);
            if (IsKeyPressed(ConsoleKey.R)) player.skills[3].Activate(player);
        }

        public static bool IsKeyDown(ConsoleKey key)
        {
            return (GetAsyncKeyState((int)key) & 0x8000) != 0;
        }

        private static readonly bool[] prevState = new bool[256];
        public static bool IsKeyPressed(ConsoleKey key)
        {
            int keyCode = (int)key;
            bool isNowPressed = (GetAsyncKeyState(keyCode) & 0x8000) != 0;
            bool pressed = isNowPressed && !prevState[keyCode]; 
            prevState[keyCode] = isNowPressed;
            return pressed;
        }

        public static void ClearKeyBuffer()
        {
            while (Console.KeyAvailable) Console.ReadKey(true);
        }
    }
}

 

 

0x8000 비트가 1이면 해당 키가 현재 눌려 있음을 의미한다.

매 프레임(루프)마다 검사하므로, 키를 꾹 누르고 있으면 계속 true가 반환된다.

 

키가 이전에 안 눌렸는데 지금 눌려있으면 KeyDown
지금 눌려있고 이전에도 눌려있으면 Hold
이전에 눌려있었는데 지금 안 눌려있으면 KeyUp
으로 구분한다.

 

 

 

이런식으로 OS의 연속 키 입력 지연과 상관없이 즉각적으로 반응하는 인풋시스템을 만들어 조작감 문제를 해결할 수 있다.

 

'C#' 카테고리의 다른 글

Design Pattern - Adapter Pattern (어댑터 패턴)  (0) 2025.10.17
C# - 콘솔로 "2중 버퍼링 (Double Buffering)" 구현하기  (0) 2025.10.15
C# - LockConsoleSize() : 콘솔 창 크기 고정 및 리사이즈 방지  (1) 2025.10.14
C# - 콘솔 폰트 크기 변경하기 SetCurrentConsoleFontEx  (1) 2025.10.13
C# - 메모리 구조, GC  (0) 2025.10.13
'C#' 카테고리의 다른 글
  • Design Pattern - Adapter Pattern (어댑터 패턴)
  • C# - 콘솔로 "2중 버퍼링 (Double Buffering)" 구현하기
  • C# - LockConsoleSize() : 콘솔 창 크기 고정 및 리사이즈 방지
  • C# - 콘솔 폰트 크기 변경하기 SetCurrentConsoleFontEx
ellug
ellug
Web / App / Game Dev
  • ellug
    dev.ellug
    ellug
  • 전체
    오늘
    어제
    • 분류 전체보기 (95)
      • Javascript (React, Next) (1)
      • C# (66)
      • Graphics (1)
      • Unity (25)
      • 프로그래머스 (0)
        • Lv.0 (0)
        • Lv.1 (0)
        • Lv.2 (0)
        • Lv.3 (0)
      • AI Agent (0)
      • StableDiffusion (0)
      • ETC (1)
      • 잡담 (0)
      • 유머 (0)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    inputsystem
    C#
    콘솔
    struct
    터미널
    네트워크
    클래스
    알고리즘
    최적화
    Network
    Abstract
    Queue
    firebase
    Design Pattern
    delegate
    list
    console
    스택
    Photon
    자료구조
    게임
    stack
    추상 클래스
    function
    useState
    큐
    유니티
    unity
    interface
    class
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
ellug
C# - GetAsnycKeyState() 기반 실시간 키 입력 처리
상단으로

티스토리툴바