Unity里实现Hook函数

一.什么是钩子函数?

先来看一段百科:钩子函数是Windows消息处理机制的一部分,通过设置“钩子”,应用程序可以在系统级对所有消息、事件进行过滤,访问在正常情况下无法访问的消息。钩子的本质是一段用以处理系统消息的程序,通过系统调用,把它挂入系统。

get关键词,在系统级对所有消息进行过滤,就是说钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作。一段用以处理系统消息的程序,用以处理系统消息的程序,是说钩子函数是用于处理系统消息的。

总结一下:

钩子函数:
1、是个函数,在系统消息触发时被系统调用
2、不是用户自己触发的

钩子函数的名称是确定的,当系统消息触发,自动会调用。例如react的componentWillUpdate函数,用户只需要编写componentWillUpdate的函数体,当组件状态改变要更新时,系统就会调用componentWillUpdate。
常见的钩子函数:
react的生命周期函数、vue的生命周期函数等

二.Unity中可以用的Hook函数

分享公司大佬的Misaka Mikoto的https://github.com/easy66/MonoHooker,

特点:

  • 运行时直接修改内存中的 jit 代码,不会修改 UnityEditor.dll 等文件,避免让别人修改文件的尴尬。
  • 不影响调试。
  • 同时支持 .net 2.x 与 .net 4.x。
  • 目前测试支持 unity4.7.2, unity5.x, unity 2017 与 unity 2018。
  • 使用很方便,在C#内定义签名与原始方法相同的两个方法然后注册一下就能用了。
  • 目前已支持 Android Mono, Windows Mono/IL2CPP

三.在项目中遇到的问题中的使用

定位一个FxClear的cs,被添加两次,看着逻辑本身没有什么问题,还是不清楚哪里让Fxclear被添加两次。通过hook函数定位到问题在哪里了.

FxClear有[RequireComponent(typeof(ParticleLOD))],而ParticleLOD在Awake()里有gameObject.GetOrAddComponent();
修改到Start();

particleSystem的Render 的enable被设置为false。之前在所有render被改为false的地方加断点,没断到。通过hook函数成功定位到了问题。

GetComponentsInChildren();
当某个节点setactive(false)的时候,在子节点的render并不会被Get到。解决方案是GetComponentsInChildren(true);

四.怎么做到呢

底层是汇编,在x8,x64上不同的处理,因为我也缺少汇编相关的知识,请大佬讲解了下,push作为一个函数的开始,ret是函数的结束。

在push函数地址替换成自己用的函数地址,执行完毕再继续执行原来的函数,通过这样达到hook,在不同的环境可以使用。当然也要函数长度满足8个字节长度。

因为也支持arm环境。发现设备环境确实有点不一样的。

同样不影响执行的效率。

文章目录
  1. 1. 一.什么是钩子函数?
  2. 2. 二.Unity中可以用的Hook函数
  3. 3. 三.在项目中遇到的问题中的使用
    1. 3.0.1. 定位一个FxClear的cs,被添加两次,看着逻辑本身没有什么问题,还是不清楚哪里让Fxclear被添加两次。通过hook函数定位到问题在哪里了.
    2. 3.0.2. particleSystem的Render 的enable被设置为false。之前在所有render被改为false的地方加断点,没断到。通过hook函数成功定位到了问题。
  • 4. 四.怎么做到呢
  • |