다음을 통해 공유


레이싱 휠 및 포스 피드백

이 페이지에서는 Windows.Gaming.Input.RacingWheel 을 사용하는 Xbox One의 레이싱 휠에 대한 프로그래밍의 기본 사항과 UWP(유니버설 Windows 플랫폼)용 관련 API에 대해 설명합니다.

이 페이지를 읽으면 다음에 대해 알아봅니다.

  • 연결된 레이싱 휠 및 해당 사용자 목록을 수집하는 방법
  • 레이싱 휠이 추가 또는 제거되었음을 감지하는 방법
  • 하나 이상의 레이싱 휠에서 입력을 읽는 방법
  • 힘 피드백 명령을 보내는 방법
  • 레이싱 휠이 UI 탐색 장치로 작동하는 방식

레이싱 휠 개요

레이싱 휠은 실제 레이스카 조종석의 느낌과 유사한 입력 장치입니다. 레이싱 휠은 자동차 또는 트럭을 특징으로하는 아케이드 스타일과 시뮬레이션 스타일의 레이싱 게임 모두를위한 완벽한 입력 장치입니다. 레이싱 휠은 Windows.Gaming.Input 네임스페이스에서 Windows 10 또는 Windows 11 및 Xbox One UWP 앱에서 지원됩니다.

레이싱 휠은 다양한 가격대에서 제공되며, 일반적으로 가격 포인트가 상승함에 따라 점점 더 나은 입력 및 힘 피드백 기능을 갖습니다. 모든 레이싱 휠에는 아날로그 스티어링 휠, 아날로그 스로틀 및 브레이크 컨트롤, 일부 온 휠 버튼이 장착되어 있습니다. 일부 레이싱 휠에는 아날로그 클러치 및 핸드 브레이크 컨트롤, 패턴 시프터 및 힘 피드백 기능이 추가로 장착되어 있습니다. 모든 레이싱 휠에 동일한 기능 집합이 장착되는 것은 아니며 특정 기능에 대한 지원도 달라질 수 있습니다. 예를 들어 스티어링 휠은 다양한 회전 범위를 지원할 수 있으며 패턴 시프터는 다양한 수의 기어를 지원할 수 있습니다.

디바이스 성능

다양한 레이싱 휠은 다양한 선택적 장치 기능 세트와 이러한 기능에 대한 다양한 수준의 지원을 제공합니다. 단일 종류의 입력 디바이스 간의 이 변형 수준은 Windows.Gaming.Input API에서 지원하는 디바이스 중에서 고유합니다. 또한, 여러분이 접하게 될 대부분의 기기는 적어도 일부 선택적인 기능이나 다른 형태를 지원할 것입니다. 이 때문에 연결된 각 레이싱 휠의 기능을 개별적으로 결정하고 게임에 적합한 기능의 전체 변형을 지원하는 것이 중요합니다.

자세한 내용은 레이싱 휠 기능 결정을 참조하세요.

강제적 피드백

일부 레이싱 휠은 진정한 힘 피드백을 제공합니다. 즉, 단순한 진동뿐만 아니라 스티어링 휠과 같은 컨트롤 축에 실제 힘을 적용할 수 있습니다. 게임은 이 기능을 사용하여 더욱 몰입감을 높이고 운전의 난이도를 높입니다 (시뮬레이션된 충돌 피해, "도로 느낌").

자세한 내용은 힘 피드백 개요을 참조하세요.

UI 탐색

사용자 인터페이스 탐색을 위해 다양한 입력 디바이스를 지원하는 부담을 덜고 게임과 디바이스 간의 일관성을 장려하기 위해 대부분의 물리적 입력 디바이스는 동시에 UI 탐색 컨트롤러라는 별도의 논리적 입력 디바이스 역할을. UI 탐색 컨트롤러는 입력 디바이스에서 UI 탐색 명령에 대한 일반적인 어휘를 제공합니다.

아날로그 컨트롤에 대한 고유한 초점과 다양한 레이싱 휠 간의 변형 정도로 인해 일반적으로 디지털 D 패드, 보기, 메뉴, A, B, X게임 패드와 유사한 Y 단추가; 이러한 단추는 게임 플레이 명령을 지원하기 위한 것이 아니며 레이싱 휠 단추로 쉽게 액세스할 수 없습니다.

UI 탐색 컨트롤러로서 레이싱 휠은 탐색 명령의 필수 집합 왼쪽 엄지스틱, D 패드, 보기, 메뉴, AB 단추에 매핑합니다.

탐색 명령 레이싱 휠 입력
위로 D 패드 위 방향으로
아래로 D 패드 아래로
왼쪽 왼쪽 D 패드
오른쪽 오른쪽 D 패드
보기 보기 버튼
메뉴 메뉴 단추
받아들이다 단추
취소 B 버튼

또한 일부 레이싱 휠은 선택적 집합 내의 탐색 명령 중 일부를 그들이 지원하는 다른 입력에 매핑할 수 있지만, 명령 매핑은 기기마다 다를 수 있습니다. 이러한 명령도 지원하는 것이 좋지만 이러한 명령이 게임의 인터페이스를 탐색하는 데 필수적이지 않은지 확인합니다.

탐색 명령 레이싱 휠 입력
페이지 위로 다양함
페이지 아래로 이동 다양함
페이지 왼쪽 다양함
오른쪽 페이지로 이동 다양함
위로 스크롤 다양함
아래로 스크롤 다양함
왼쪽으로 스크롤 다양함
오른쪽으로 스크롤 다양함
컨텍스트 1 X 버튼(일반적으로)
컨텍스트 2 Y 단추(일반적으로)
컨텍스트 3 다양함
컨텍스트 4 다양함

레이싱 휠 감지 및 추적

레이싱 휠 감지 및 추적은 Gamepad 클래스 대신 RacingWheel 클래스를 제외하고 게임 패드와 똑같은 방식으로 작동합니다. 자세한 내용은 게임 패드 및 진동 참조하세요.

레이싱 휠 이해하기

관심 있는 레이싱 휠을 찾았으면 이제 해당 휠로부터 입력을 받을 준비가 된 것입니다. 그러나 다른 종류의 입력과 달리 레이싱 휠은 이벤트를 발생시켜 상태 변경을 전달하지 않습니다. 대신,을(를) 현재 상태로 정기적으로 폴링하여 읽습니다.

레이싱 휠 상태 확인

폴링은 정확한 시점에 레이싱 휠의 스냅샷을 캡처합니다. 입력 수집에 대한 이 접근 방식은 대부분의 게임에 적합합니다. 일반적으로 논리는 이벤트 중심이 아닌 결정적 루프에서 실행되기 때문입니다. 또한 일반적으로 시간이 지남에 따라 수집된 많은 단일 입력보다 한 번에 수집된 입력에서 게임 명령을 해석하는 것이 더 간단합니다.

GetCurrentReading를 호출하여 레이싱 휠을 폴링합니다. 이 함수는 레이싱 휠의 상태를 포함하는 RacingWheelReading을 반환합니다.

다음 예제에서는 현재 상태에 대한 레이싱 휠을 폴링합니다.

auto racingwheel = myRacingWheels[0];

RacingWheelReading reading = racingwheel->GetCurrentReading();

레이싱 휠 상태 외에도 각 판독값에는 상태를 검색한 시기를 정확하게 나타내는 타임스탬프가 포함됩니다. 타임스탬프는 이전 판독값의 타이밍 또는 게임 시뮬레이션의 타이밍과 관련된 데 유용합니다.

레이싱 휠 기능 점검

많은 레이싱 휠 컨트롤은 선택 사항이거나 필요한 컨트롤에서도 다양한 변형을 지원하므로 레이싱 휠의 각 판독값에 수집된 입력을 처리하려면 각 레이싱 휠의 기능을 개별적으로 결정해야 합니다.

선택적 컨트롤은 핸드브레이크, 클러치 및 패턴 시프터입니다. 연결된 레이싱 휠이 HasHandbrake, HasClutchHasPatternShifter 속성을 각각 읽어 이러한 컨트롤을 지원하는지 여부를 확인할 수 있습니다. 속성 값이 true경우 컨트롤이 지원됩니다. 그렇지 않으면 지원되지 않습니다.

if (racingwheel->HasHandbrake)
{
    // the handbrake is supported
}

if (racingwheel->HasClutch)
{
    // the clutch is supported
}

if (racingwheel->HasPatternShifter)
{
    // the pattern shifter is supported
}

또한, 변화할 수 있는 제어 장치는 스티어링 휠과 패턴 시프터입니다. 스티어링 휠은 실제 휠이 지원할 수 있는 물리적 회전 정도에 따라 달라질 수 있으며 패턴 시프터는 지원하는 고유한 전방 기어 수에 따라 달라질 수 있습니다. 레이싱 휠의 MaxWheelAngle 속성을 읽어 실제 휠이 지원하는 가장 큰 회전 각도를 확인할 수 있습니다. 이 값은 시계 방향(양의 각도)과 시계 반대 방향(음의 각도) 모두에서 지원되는 최대 물리적 각도입니다. 레이싱 휠의 MaxPatternShifterGear 속성을 읽어 패턴 시프터가 지원하는 가장 큰 전방 기어를 확인할 수 있습니다. 해당 값은 지원되는 가장 높은 전방 기어입니다. 즉, 값이 4이면 패턴 시프터는 역방향, 중립, 첫 번째, 두 번째, 세 번째 및 네 번째 기어를 지원합니다.

auto maxWheelDegrees = racingwheel->MaxWheelAngle;
auto maxShifterGears = racingwheel->MaxPatternShifterGear;

마지막으로, 일부 레이싱 휠은 스티어링 휠을 통해 힘 피드백을 지원합니다. 연결된 레이싱 휠이 레이싱 휠의 WheelMotor 속성을 읽어 힘 피드백을 지원하는지 여부를 확인할 수 있습니다. 만약 WheelMotor이(가) null이(가) 아니라면, 힘 피드백이 지원됩니다. 그렇지 않으면 지원되지 않습니다.

if (racingwheel->WheelMotor != nullptr)
{
    // force feedback is supported
}

이를 지원하는 레이싱 휠의 힘 피드백 기능을 사용하는 방법에 대한 자세한 내용은 Force 피드백 개요참조하세요.

버튼 읽기

D 패드의 네 방향, 이전 기어다음 기어 버튼, 그리고 16개의 추가 버튼 등 각 레이싱 휠 버튼은 누름(아래쪽) 또는 풀림(위쪽)을 나타내는 디지털 판독값을 제공합니다. 효율성을 위해 단추 판독값은 개별 부울 값으로 표시되지 않습니다. 대신 RacingWheelButtons 열거형으로 표현되는 단일 비트 필드로 압축됩니다.

비고

레이싱 휠에는 보기메뉴 단추와 같은 UI 탐색에 사용되는 추가 단추가 장착되어 있습니다. 이러한 단추는 RacingWheelButtons 열거형의 일부가 아니며 레이싱 휠을 UI 탐색 장치로 액세스해야만 읽을 수 있습니다. 자세한 내용은 UI 탐색 디바이스참조하세요.

단추 값은 Buttons 구조체의 속성에서 읽습니다. 이 속성은 비트 필드이기 때문에 비트 마스킹은 관심 있는 단추의 값을 격리하는 데 사용됩니다. 해당 비트가 설정되면 단추가 누름 상태(아래)가 되고, 그렇지 않으면 풀림 상태(위)가 됩니다.

다음 예제에서는 다음 기어 단추를 눌렀는지 여부를 확인합니다.

if (RacingWheelButtons::NextGear == (reading.Buttons & RacingWheelButtons::NextGear))
{
    // Next Gear is pressed
}

다음 예제에서는 다음 기어 버튼이 해제되었는지를 확인합니다.

if (RacingWheelButtons::None == (reading.Buttons & RacingWheelButtons::NextGear))
{
    // Next Gear is released (not pressed)
}

단추가 누름 상태에서 놓임 상태로 또는 놓임 상태에서 누름 상태로 전환하는 시기, 여러 단추가 동시에 눌리거나 놓이는 경우, 혹은 일부 단추는 눌리고 다른 일부는 눌리지 않도록 특정 방식으로 정렬되어 있는지를 확인하고 싶을 수 있습니다. 이러한 조건을 감지하는 방법에 대한 자세한 내용은 단추 전환 감지복잡한 단추 배열 감지을 참조하세요.

휠 읽기

스티어링 휠은 -1.0에서 +1.0 사이의 아날로그 판독값을 제공하는 필수 컨트롤입니다. -1.0 값은 가장 왼쪽 휠 위치에 해당합니다. 값 +1.0은 가장 오른쪽 위치에 해당합니다. 스티어링 휠의 값은 Wheel 구조체의 속성에서 읽습니다.

float wheel = reading.Wheel;  // returns a value between -1.0 and +1.0.

휠 값은 실제 레이싱 휠에서 지원하는 회전 범위에 따라 실제 휠의 다른 물리적 회전 정도에 해당하지만, 일반적으로 휠 값을 조정하려 하지는 않습니다. 회전 범위가 넓은 바퀴는 정밀도를 높여줍니다.

스로틀 및 브레이크 모니터링

스로틀 및 브레이크는 각각 부동 소수점 값으로 표현되는 0.0(완전히 놓인)과 1.0(완전히 누름) 사이의 아날로그 판독값을 제공하는 필수 컨트롤입니다. 스로틀 컨트롤의 값은 Throttle 구조체의 속성에서 읽습니다. 브레이크 컨트롤의 값은 Brake 속성에서 읽습니다.

float throttle = reading.Throttle;  // returns a value between 0.0 and 1.0
float brake    = reading.Brake;     // returns a value between 0.0 and 1.0

핸드브레이크와 클러치 이해하기

핸드브레이크와 클러치는 모두 0.0(완전 해제)에서 1.0(완전 작동) 사이의 아날로그 판독값을 제공하는 선택 가능한 조작 장치이며, 각 값은 부동 소수점으로 표현됩니다. 핸드브레이크 컨트롤의 값은 Handbrake 구조체의 속성에서 읽습니다. 클러치 컨트롤의 값은 Clutch 속성에서 읽습니다.

float handbrake = 0.0;
float clutch = 0.0;

if(racingwheel->HasHandbrake)
{
    handbrake = reading.Handbrake;  // returns a value between 0.0 and 1.0
}

if(racingwheel->HasClutch)
{
    clutch = reading.Clutch;        // returns a value between 0.0 and 1.0
}

패턴 전환기 이해하기

패턴 시프터는 서명된 정수 값으로 표시되는 -1 및 MaxPatternShifterGear 간에 디지털 판독값을 제공하는 선택적 컨트롤입니다. 값 -1 또는 0은 각각 후진 기어 및 중립 기어에 해당합니다. 양수 값이 커질수록 점차 앞쪽 기어에 해당하며, MaxPatternShifterGear까지 포함됩니다. 패턴 시프터의 값은 RacingWheelReading 구조체의 PatternShifterGear 속성에서 읽습니다.

if (racingwheel->HasPatternShifter)
{
    gear = reading.PatternShifterGear;
}

비고

지원되는 경우, 패턴 시프터는 반드시 필요한 이전 기어다음 기어 버튼과 함께 존재하며 이는 플레이어의 차량의 현재 기어에 영향을 미칩니다. 이러한 입력을 통합하기 위한 간단한 전략은 플레이어가 자동차의 자동 변속기를 선택한 경우 패턴 시프터와 클러치를 무시하고, 플레이어가 레이싱 휠에 패턴 시프터 컨트롤을 장착한 경우에만 자동차의 수동 변속기를 선택할 때 이전다음 기어 버튼을 무시하는 것입니다. 게임에 적합하지 않은 경우 다른 통합 전략을 구현할 수 있습니다.

InputInterfacing 샘플을 실행하십시오

GitHub의 InputInterfacingUWP 샘플 앱은 레이싱 휠 및 다양한 종류의 입력 장치를 함께 사용하는 방법을 보여 줍니다. 뿐만 아니라 이러한 입력 디바이스가 UI 탐색 컨트롤러로 동작하는 방식도 있습니다.

포스 피드백 개요

많은 레이싱 휠에는 보다 몰입감 있고 도전적인 주행 환경을 제공하기 위한 힘 피드백 기능이 있습니다. 힘 피드백을 지원하는 레이싱 휠에는 일반적으로 휠 회전 축인 단일 축을 따라 스티어링 휠에 힘을 적용하는 단일 모터가 장착되어 있습니다. 강제 피드백은 Windows.Gaming.Input.ForceFeedback 네임스페이스를 통해 Windows 10 또는 Windows 11 및 Xbox One UWP 앱에서 지원됩니다.

비고

힘 피드백 API는 여러 축의 힘을 지원할 수 있지만 현재 휠 회전 이외의 피드백 축을 지원하는 레이싱 휠은 없습니다.

힘 피드백 사용

이 섹션에서는 레이싱 휠에 대한 프로그래밍 힘 피드백 효과의 기본 사항을 설명합니다. 피드백은 효과(힘 피드백 디바이스에 먼저 로드된 후 소리 효과와 유사한 방식으로 시작, 일시 중지, 다시 시작 및 중지될 수 있는 효과)를 사용하여 적용됩니다. 그러나 먼저 레이싱 휠의 피드백 기능을 결정해야 합니다.

힘 피드백 기능을 결정하기

연결된 레이싱 휠이 레이싱 휠의 WheelMotor 속성을 읽어 힘 피드백을 지원하는지 여부를 확인할 수 있습니다. WheelMotornull인 경우 강제 피드백이 지원되지 않습니다. 그렇지 않으면 강제 피드백이 지원되며, 영향을 줄 수 있는 축과 같은 모터의 특정 피드백 기능을 확인할 수 있습니다.

if (racingwheel->WheelMotor != nullptr)
{
    auto axes = racingwheel->WheelMotor->SupportedAxes;

    if(ForceFeedbackEffectAxes::X == (axes & ForceFeedbackEffectAxes::X))
    {
        // Force can be applied through the X axis
    }

    if(ForceFeedbackEffectAxes::Y == (axes & ForceFeedbackEffectAxes::Y))
    {
        // Force can be applied through the Y axis
    }

    if(ForceFeedbackEffectAxes::Z == (axes & ForceFeedbackEffectAxes::Z))
    {
        // Force can be applied through the Z axis
    }
}

힘 피드백 효과 불러오기

힘 피드백 효과는 게임의 명령에 따라 자율적으로 작동되는 피드백 장치에 로드됩니다. 다양한 기본 효과가 제공됩니다. 사용자 지정 효과는 IForceFeedbackEffect 인터페이스를 구현하는 클래스를 통해 만들 수 있습니다.

효과 클래스 효과 설명
조건 강제 효과 디바이스 내의 현재 센서에 응답하여 가변 힘을 적용하는 효과입니다.
일정 힘 효과 벡터에 상수 힘을 적용하는 효과입니다.
주기적 힘 효과 벡터를 따라 파형에 의해 정의된 가변 힘을 적용하는 효과입니다.
램프포스이펙트 벡터를 따라 선형으로 증가/감소하는 힘을 적용하는 효과입니다.
using FFLoadEffectResult = ForceFeedback::ForceFeedbackLoadEffectResult;

auto effect = ref new Windows.Gaming::Input::ForceFeedback::ConstantForceEffect();
auto time = TimeSpan(10000);

effect->SetParameters(Windows::Foundation::Numerics::float3(1.0f, 0.0f, 0.0f), time);

// Here, we assume 'racingwheel' is valid and supports force feedback

IAsyncOperation<FFLoadEffectResult>^ request
    = racingwheel->WheelMotor->LoadEffectAsync(effect);

auto loadEffectTask = Concurrency::create_task(request);

loadEffectTask.then([this](FFLoadEffectResult result)
{
    if (FFLoadEffectResult::Succeeded == result)
    {
        // effect successfully loaded
    }
    else
    {
        // effect failed to load
    }
}).wait();

힘 피드백 효과 사용

로드되면 레이싱 휠의 WheelMotor 속성에서 함수를 호출하거나 피드백 효과 자체에 대한 함수를 개별적으로 호출하여 모든 효과를 시작, 일시 중지, 다시 시작 및 중지할 수 있습니다. 일반적으로 게임 플레이가 시작되기 전에 사용하려는 모든 효과를 피드백 디바이스에 로드한 다음 해당 SetParameters 함수를 사용하여 게임 플레이가 진행됨에 따라 효과를 업데이트해야 합니다.

if (ForceFeedbackEffectState::Running == effect->State)
{
    effect->Stop();
}
else
{
    effect->Start();
}

마지막으로 필요할 때마다 특정 레이싱 휠에서 전체 힘 피드백 시스템을 비동기적으로 사용하거나 사용하지 않도록 설정하거나 재설정할 수 있습니다.

참고하십시오