谷桐羽 2026-05-16 18:40 采纳率: 98.8%
浏览 0
已采纳

Horizoverlay悬浮窗不显示伤害数据或无法正确对齐?

Horizoverlay悬浮窗不显示伤害数据或无法正确对齐,常见于游戏Hook注入失败或目标进程内存读取异常。典型原因包括:① 游戏更新后关键内存地址偏移变动,导致伤害结构体解析失败;② DirectX/OpenGL渲染上下文切换时UI线程未同步,造成坐标计算偏差(尤其在多显示器或高DPI缩放场景下);③ 悬浮窗启用硬件加速但未正确处理窗口层级(如被游戏UI遮挡或Z-order错乱);④ 数据采集模块(如Detours Hook或DMA读取)权限不足或被反作弊拦截,致使伤害事件未触发回调。调试时建议优先验证日志输出是否捕获到原始伤害包,再检查`GetWindowRect`与`SetWindowPos`坐标转换逻辑是否适配当前DPI缩放比例(需调用`SetProcessDpiAwarenessContext`)。该问题在《原神》《崩坏:星穹铁道》等Unity引擎游戏中尤为高频。
  • 写回答

1条回答 默认 最新

  • 猴子哈哈 2026-05-16 18:40
    关注
    ```html

    一、现象层:悬浮窗“失联”——可见性与对齐异常的表征诊断

    Horizoverlay 在《原神》《崩坏:星穹铁道》等 Unity 游戏中常表现为:伤害数字完全不渲染、零散闪烁、坐标漂移(如始终偏移屏幕右上角 200px)、或被游戏 UI 严密封锁(Z-order 归零)。该层级问题无需深入内存,仅通过视觉+日志即可快速归类。建议启动时启用 --debug-overlay 参数并捕获 OverlayRenderLoop 帧率与 DamageEventQueue.Size() 实时输出——若队列持续为 0,则问题已下沉至数据采集层。

    二、数据层:Hook 失效与 DMA 中断——原始伤害包的“消失之谜”

    • Unity IL2CPP 混淆后,DamageInfo 结构体在 Assembly-CSharp.dll 中的 RVA 偏移随热更新频繁变动(如 v4.6 → v4.7 变更 +0x1C → +0x28);
    • 反作弊系统(如米哈游自研 MhyProt、Easy Anti-Cheat)主动扫描 Detours::DetourAttach 的 IAT 修改痕迹,触发进程挂起或 STATUS_ACCESS_VIOLATION
    • DMA 方案在 Windows 11 22H2+ 启用 HVCI(Hypervisor-protected Code Integrity)后,MapPhysicalMemory 调用直接返回 STATUS_INVALID_PARAMETER

    验证手段:使用 Process Hacker 2 查看目标进程的模块基址与内存保护属性(重点关注 MEM_COMMIT | PAGE_EXECUTE_READWRITE 是否被降级)。

    三、坐标层:DPI 与渲染上下文撕裂——多屏高缩放下的几何灾难

    场景GetWindowRect 返回值真实 DPI 缩放SetWindowPos 偏差
    单屏 125%(100,100,300,200)125%需乘以 1.25 → (125,125,375,250)
    双屏(主屏100%+副屏150%)仍返回逻辑像素副屏实际缩放 1.5x未调用 SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) 将导致坐标错乱达 ±40px

    四、渲染层:硬件加速与窗口层级博弈——GPU 合成中的 Z-order 黑箱

    当 Horizoverlay 启用 WS_EX_LAYERED | WS_EX_TRANSPARENT 并调用 UpdateLayeredWindow 时,若未同步设置 HWND_TOPMOST 且未处理 WM_WINDOWPOSCHANGING 消息拦截,Windows DWM 将按默认 Z-order 排序——而 Unity 游戏常通过 SetWindowPos(hwndGame, HWND_NOTOPMOST, ...) 主动降级自身层级,导致 overlay 被压在游戏窗口之下。解决方案需双管齐下:

    1. 注册全局钩子监听 WH_CALLWNDPROC 捕获游戏窗口的 WM_WINDOWPOSCHANGED
    2. WM_TIMER 中每 33ms 调用 SetWindowPos(overlayHwnd, HWND_TOPMOST, ...) 强制置顶。

    五、架构层:Unity 引擎特异性适配——IL2CPP 符号解析与 MonoManager 动态定位

    // Unity v2021.3+ IL2CPP 中 DamageEvent 的典型定位链(需 runtime 解析)
    auto mono_image = il2cpp_image_open("Assembly-CSharp.dll");
    auto klass = il2cpp_class_from_name(mono_image, "GlobalNamespace", "DamageInfo");
    auto field = il2cpp_class_get_field_from_name(klass, "damageValue"); // offset now volatile!
    // 必须结合符号服务器(如 Unity Symbol Server)或 .pdb 解析动态 RVA
    

    六、调试流:结构化排障路径(Mermaid 流程图)

    graph TD A[启动 Horizoverlay] --> B{日志中 DamageEventQueue.Size > 0?} B -->|否| C[检查 Hook/DMA 权限与反作弊拦截] B -->|是| D[检查 GetWindowRect 坐标是否经 DPI 缩放校正] C --> E[Process Hacker 验证内存页属性] D --> F[调用 SetProcessDpiAwarenessContext] E --> G[尝试 EAC 兼容 Hook:MinHook + inline hook on il2cpp_add_assembly] F --> H[注入 SetThreadDpiAwarenessContext 到游戏主线程] G --> I[成功捕获原始伤害包] H --> J[Overlay 坐标精准对齐] I --> J
    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 今天
  • 创建了问题 5月16日