PAYATHON 2026

如何在 Dear ImGui 中读取 gamepad 的模拟量?

数据小陈

可以通过 ImGui::GetKeyData(key)->AnalogValue 读取 Dear ImGui 保存的 gamepad 模拟量。IsKeyDown() 和 IsKeyPressed() 只返回布尔状态,无法给出摇杆偏转或扳机按压的具体数值。

GetKeyData() 是内部 API。以下示例以 Dear ImGui v1.90 为例,需要包含同一版本的 imgui_internal.h;升级时应检查接口是否有变化。接口声明及兼容性说明

读取摇杆和扳机的代码示例

调用前,请确认已经创建 Dear ImGui context、平台后端已初始化,且后端正在提交 gamepad 输入。在平台后端更新、ImGui::NewFrame() 执行之后调用以下函数:

#include "imgui.h"
#include "imgui_internal.h"

static float ReadGamepadAnalog(ImGuiKey key)
{
    return ImGui::GetKeyData(key)->AnalogValue;
}

void ShowGamepadValues()
{
    const float left_x =
        ReadGamepadAnalog(ImGuiKey_GamepadLStickRight) -
        ReadGamepadAnalog(ImGuiKey_GamepadLStickLeft);

    const float left_y =
        ReadGamepadAnalog(ImGuiKey_GamepadLStickDown) -
        ReadGamepadAnalog(ImGuiKey_GamepadLStickUp);

    const float left_trigger =
        ReadGamepadAnalog(ImGuiKey_GamepadL2);
    const float right_trigger =
        ReadGamepadAnalog(ImGuiKey_GamepadR2);

    ImGui::Begin("Gamepad values");
    ImGui::Text("Left stick: x=%.3f, y=%.3f", left_x, left_y);
    ImGui::Text("Triggers: left=%.3f, right=%.3f",
                left_trigger, right_trigger);
    ImGui::End();
}

Dear ImGui 将摇杆分为左、右、上、下四个方向,每个方向的 AnalogValue 范围为 0.0f..1.0f。示例将相反方向的值相减,得到两个轴,范围为 -1.0f..1.0f,其中 X 向右为正、Y 向下为正。扳机使用 ImGuiKey_GamepadL2 和 ImGuiKey_GamepadR2。模拟量字段及 gamepad 枚举

数值始终为 0 时检查什么

先确认平台后端是否支持并检测到了手柄,以及后端的 NewFrame() 是否每帧执行。仅加入读取代码,Dear ImGui 不会自动获取硬件数据。

使用官方 GLFW 后端时,还需要在初始化阶段启用以下配置:

ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;

该配置会启用手柄导航。所查阅的 GLFW 后端实现也根据它决定是否提交 gamepad 输入;其他后端的行为应以对应版本的实现为准。ImGuiBackendFlags_HasGamepad 由后端维护,不应手动设置来代替设备检测。GLFW 后端实现

如果使用自定义后端,需要在 ImGui::NewFrame() 之前通过 io.AddKeyAnalogEvent(key, down, value) 提交模拟输入,并在后端处理死区。down 表示按下状态,value 表示模拟强度,两者含义不同。

版本和数值含义的注意事项

原问题写的是 v1.9,无法确认实际使用的完整版本号。请查看项目中的 IMGUI_VERSION。上述示例基于 v1.90 的接口,不能据此认定 IsKeyDown / IsKeyPressed 首次出现于 v1.9。

读取到的值由后端提交给 Dear ImGui,可能已经经过死区处理、缩放和限幅。例如,官方 GLFW 后端会转换摇杆轴值。因此,相减得到的坐标也不等同于手柄的原始硬件读数。如果需要原始轴值,应从应用使用的输入库或平台 API 读取。

不要直接用 io.KeysData[key] 访问数据,其索引布局可能受版本和编译选项影响。使用内部读取接口时,也要确保头文件与编译的 Dear ImGui 源码版本一致。输入接口和内部数据说明

备注:内容仅供参考。