在windows的游戏控制器里看,数据是连贯的,但是用rawinput看,数据平均分成了两部分,静止的时候是0.5,推到中间是1,再继续往前推立刻就变成0了,然后推到头又变成0.5
请问怎么样让它是一段连贯的数据
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
这可能是由于UE4对输入设备的输入数据处理方式不同于Windows游戏控制器的原因导致的。UE4在处理输入数据时会进行一些中间处理,使得输入的轴数据呈现出了分段的状态。
要解决这个问题,可以通过在UE4中注册轴事件并手动处理RawInput数据来获得连续的轴数据。具体步骤如下:
首先,使用RawInput API注册输入设备并获取其句柄。
RAWINPUTDEVICE rid = {};
rid.usUsagePage = 0x01;
rid.usUsage = 0x04; // joystick
rid.dwFlags = RIDEV_INPUTSINK;
rid.hwndTarget = hWnd; //窗口句柄,可以从UE4获取
if (RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)) == FALSE)
{
// 处理注册失败的情况
}
在UE4的输入类中创建一个轴事件,并将其绑定到RawInput轴的通知函数中。在通知函数中将RawInput数据传递给轴事件以手动处理数据。
// 在输入类中定义一个轴事件
UFUNCTION(BlueprintImplementableEvent, Category = "Input")
void OnJoystickAxis(float X, float Y);
// RawInput轴通知函数
LRESULT WINAPI RawInputAxis(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// 使用GetRawInputData()获取输入数据
RAWINPUT rawInput;
UINT size = sizeof(RAWINPUT);
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &rawInput, &size, sizeof(RAWINPUTHEADER)) != UINT(-1))
{
if (rawInput.header.dwType == RIM_TYPEHID && rawInput.hid.dwSizeHid >= sizeof(HIDP_VALUE_CAPS))
{
HIDP_VALUE_CAPS valueCaps;
USHORT numValues = 0;
PHIDP_PREPARSED_DATA pData = nullptr;
if (HidP_GetPreparsedData(rawInput.hid.bRawData, &pData) == HIDP_STATUS_SUCCESS)
{
HidP_GetValueCaps(HidP_Input, &valueCaps, &numValues, pData);
if (numValues > 0)
{
HIDP_VALUE_CAPS* pValueCaps = new HIDP_VALUE_CAPS[numValues];
if (HidP_GetValueCaps(HidP_Input, pValueCaps, &numValues, pData) == HIDP_STATUS_SUCCESS)
{
// 解析轴数据
for (USHORT i = 0; i < numValues; ++i)
{
if (HidP_IsAxis(pValueCaps[i].UsagePage, pValueCaps[i].LogicalMin, pValueCaps[i].LogicalMax))
{
LONG value = 0;
if (HidP_GetUsageValue(HidP_Input, pValueCaps[i].UsagePage, 0, pValueCaps[i].NotRange.Usage, &value, pData, rawInput.hid.bRawData, rawInput.hid.dwSizeHid) == HIDP_STATUS_SUCCESS)
{
float axisValue = (value - pValueCaps[i].LogicalMin) / static_cast<float>(pValueCaps[i].LogicalMax - pValueCaps[i].LogicalMin) * 2.f - 1.f;
// 触发轴事件
UGameViewportClient* viewport = GEngine->GameViewport;
if (viewport)
{
APlayerController* controller = viewport->GetWorld()->GetFirstPlayerController();
if (controller)
{
controller->ProcessEvent(controller->FindFunctionChecked("OnJoystickAxis"), &axisValue, 1);
}
}
}
}
}
}
delete[] pValueCaps;
}
HidD_FreePreparsedData(pData);
}
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
最后,在项目中找到输入类并重写OnJoystickAxis事件以获取连续的轴数据。
void AMyPlayer::OnJoystickAxis(float X, float Y)
{
// 可以直接使用手柄的X和Y轴数据
// 处理连续的轴数据
}
使用这种方式可以手动处理RawInput数据并获得连续的轴数据,从而解决分段的问题。
如果我的回答解决了您的问题,请采纳!
该回答引用chatgpt:
这可能是因为你没有正确处理RawInput的InputData。在RawInput中,轴数据是通过指定的轴值(一般为-32768到32767的整数)来表示的。UE4会将这些轴值归一化为0.0到1.0之间的浮点数,以便于在游戏中使用。因此,当你使用RawInput时,需要正确地处理归一化后的轴数据,以便获得正确的连续轴数据。
以下是一些代码示例,可以帮助你正确处理轴数据:
// 处理 WM_INPUT 消息
LRESULT CALLBACK RawInputWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INPUT:
{
// 获取输入数据
RAWINPUT rawInput;
UINT size = sizeof(rawInput);
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &rawInput, &size, sizeof(RAWINPUTHEADER));
// 处理轴数据
if (rawInput.header.dwType == RIM_TYPEHID && rawInput.hid.dwType == RIM_TYPEHID && rawInput.hid.dwCount > 0)
{
PHIDP_PREPARSED_DATA preparsedData;
HIDP_CAPS caps;
HIDP_VALUE_CAPS valueCaps;
NTSTATUS status = HidP_GetPreparsedData(rawInput.hid.bRawData, &preparsedData);
status = HidP_GetCaps(preparsedData, &caps);
ULONG valueCapsLength = caps.NumberInputValueCaps;
PHIDP_VALUE_CAPS pHidValueCaps = new HIDP_VALUE_CAPS[valueCapsLength];
status = HidP_GetValueCaps(HidP_Input, pHidValueCaps, &valueCapsLength, preparsedData);
for (int i = 0; i < valueCapsLength; i++)
{
// 处理轴数据
if (pHidValueCaps[i].IsRange == FALSE && pHidValueCaps[i].UsagePage == HID_USAGE_PAGE_GENERIC &&
pHidValueCaps[i].LinkCollection == 0 && pHidValueCaps[i].Usage == HID_USAGE_GENERIC_X)
{
LONG value = rawInput.hid.dwRawData[pHidValueCaps[i].ByteOffset];
float axisValue = (value - -32768.0f) / (32767.0f - -32768.0f); // 归一化轴值为0.0到1.0之间的浮点数
// 处理轴数据的连续性,例如使用缓存存储前一个轴数据的值,并在当前值与前一个值之间进行插值。
// 这里只是简单地将轴数据的值输出到控制台,用于演示如何正确处理轴数据。
std::cout << "Axis X: " << axisValue << std::endl;
}
}
delete[] pHidValueCaps;
HidD_FreePreparsedData(preparsedData);
}
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
引用chatGPT作答,这种情况可能是因为您没有正确处理RawInput传递的输入数据。您需要对数据进行解析和处理,以便正确地将其转换为轴输入值。以下是一些可能有用的步骤:
1.确保您正在读取正确的数据,这可能需要查看输入报告的格式和结构。
2.计算轴的值应该是多少,这可能涉及到将原始数据映射到轴的范围。
3.确保您处理轴输入的所有状态,包括轴值为零和轴值达到最大/最小值的情况。
4.如果您的游戏控制器支持多个轴,请确保您正确地识别和处理每个轴