记录一个由于GMP参数类型不匹配导致的BUG
记录一个由于GMP参数类型不匹配导致的BUG
原因在于一次用GMP的SendObjectMessage
时我写了如下代码:
其中SourceActo
r是一个Actor*
类型, Character
是一个Character*
类型, 代表着 SourceActor把Character的盾击碎。
而在声明这个MessageKey
时,由于想到这个MessageKey
会被其他两个物体用到,比如炮台A击碎了炮塔B的护盾,那么这个Message的两个参数类型如果分别设置为Actor和Character显然是不合理的,因此选择了声明为两个Actor,如下图:
把Character*
类型UpCast传给Actor*
显然是正确的,是常用的多态特性而已。
在编辑器中一切正常,而打包出来的游戏却异常,表现为:GMP在Listen到Message后没有执行后续的操作
这太奇怪了,看Log发现了一些事情:
UGMPManager::IsSignatureCompatible
这个函数报错,发现了签名不匹配导致了后续操作被拒绝:
不匹配具体表现为:下面这两个if没有一个可以通过
rhsName就是(Actor,Actor)即MessageKey中的类型,lhsName就是SendObject中参数的类型(Actor,Character)。
在这rhs和lhs匹配时,他们的第二个参数分别为Actor和Character,Actor和Character出现了不是IsDerivedFrom的关系,可是这俩事实上确实是继承关系,为什么会检测不到呢?更奇怪的是在编辑器中却可以检测到有继承关系。
接着看继承关系的信息怎么来的:
查看这个Info怎么来的:存储在静态数据中
再看静态数据怎么被维护的:在调用GetClassName/GetNativeClassName中被维护到
以GetNativeClassName为例:再看谁调用了GetNativeClassName
可以看到在Edtior宏包围了这个GetNativeClassName,这导致了:在编辑器中继承链上的继承信息可以被收集到,而在打包出来的游戏中无法收集到, 从而导致了最开始的类型不匹配。
GMP作者肯定是认为继承关系信息的收集是很耗费时间的,所以包了一层Editor的宏,防止在游戏包体中做这种耗时操作,但是这却导致了一个令人困惑的Bug,即文章一开始所说的在打包和编辑器中的差异。
回到最开始的问题,我还是希望MessageKey的参数是(Actor,Actor),怎么办呢?希望这么做的原因在文章开头提到了(即希望这个MessageKey可以被其他非Character的Actor类型复用),我们直接在发消息前UpCast一下即可,提前做一个转换。
到此问题解决。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!