Unity在il2cpp后端使用反射时的问题

日前在项目中需要查询UnityEvent中所有注册的listener的数量,包括Persistent listener和Non-persistent listener。而Unity中仅提供了查询Persistent listener的API:

所以开发者就需要自己想办法来获取这个数量。目前主要有两个思路:
1. 通过反射:

https://forum.unity.com/threads/get-number-of-runtime-listeners.292537/

public static int GetListenerNumber(this UnityEventBase unityEvent)
{
    var field = typeof(UnityEventBase).GetField("m_Calls", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly );
    var invokeCallList = field.GetValue(unityEvent);
    var property = invokeCallList.GetType().GetProperty("Count");
    return (int)property.GetValue(invokeCallList);
}

2. 通过继承UnityEvent后自行在Add/Remove listener的API中计数。这种方式比较繁琐,相比而言不优雅,而且可能造成一堆的冗余代码。

可是,在使用反射获取UnityEventBase中类型为InvokeCallList私有变量m_Calls,在Mono下使用无虞,可是转到il2cpp之后就会抛异常,程序逻辑无法正常进行。

https://github.com/Unity-Technologies/UnityCsReference/blob/667dd8bc523315986521ee31df35cb9e584049b9/Runtime/Export/UnityEvent/UnityEvent.cs#L664

通过一顿查找、试验,最后终于在forum中找到相关线索:

https://forum.unity.com/threads/unity-5-0-3f2-il2cpp-problem-attempting-to-call-method-system-reflection-monoproperty-getteradapt.332335/page-3

基本上的思路可以是:
1.

#if AOT
    return ((PropertyInfo)member).GetGetMethod().Invoke(target, null);
#else
    return ((PropertyInfo)member).GetValue(target, null);
#endif

2. 或者修改Unity的link.xml,让Unity不要去除掉一些符号:

<assembly fullname="UnityEngine.CoreModule">
    <type fullname="UnityEngine.Events.InvokableCallList" preserve="all" />
</assembly>
打赏

沪公网安备 31011302002866号