记录一个由于GMP参数类型不匹配导致的BUG

记录一个由于GMP参数类型不匹配导致的BUG

原因在于一次用GMP的SendObjectMessage时我写了如下代码:

其中SourceActor是一个Actor*类型, Character是一个Character*类型, 代表着 SourceActor把Character的盾击碎。

image-20230322202648972

而在声明这个MessageKey时,由于想到这个MessageKey会被其他两个物体用到,比如炮台A击碎了炮塔B的护盾,那么这个Message的两个参数类型如果分别设置为Actor和Character显然是不合理的,因此选择了声明为两个Actor,如下图:

image-20230322202956837

Character*类型UpCast传给Actor*显然是正确的,是常用的多态特性而已。

在编辑器中一切正常,而打包出来的游戏却异常,表现为:GMP在Listen到Message后没有执行后续的操作

这太奇怪了,看Log发现了一些事情:

UGMPManager::IsSignatureCompatible这个函数报错,发现了签名不匹配导致了后续操作被拒绝:

不匹配具体表现为:下面这两个if没有一个可以通过

image-20230322204100306

rhsName就是(Actor,Actor)即MessageKey中的类型,lhsName就是SendObject中参数的类型(Actor,Character)。

在这rhs和lhs匹配时,他们的第二个参数分别为Actor和Character,Actor和Character出现了不是IsDerivedFrom的关系,可是这俩事实上确实是继承关系,为什么会检测不到呢?更奇怪的是在编辑器中却可以检测到有继承关系。

接着看继承关系的信息怎么来的:

image-20230322204543503

查看这个Info怎么来的:存储在静态数据中

image-20230322204606070

再看静态数据怎么被维护的:在调用GetClassName/GetNativeClassName中被维护到

image-20230322204653247

以GetNativeClassName为例:再看谁调用了GetNativeClassName

image-20230322203830445

可以看到在Edtior宏包围了这个GetNativeClassName,这导致了:在编辑器中继承链上的继承信息可以被收集到,而在打包出来的游戏中无法收集到, 从而导致了最开始的类型不匹配。

GMP作者肯定是认为继承关系信息的收集是很耗费时间的,所以包了一层Editor的宏,防止在游戏包体中做这种耗时操作,但是这却导致了一个令人困惑的Bug,即文章一开始所说的在打包和编辑器中的差异。

回到最开始的问题,我还是希望MessageKey的参数是(Actor,Actor),怎么办呢?希望这么做的原因在文章开头提到了(即希望这个MessageKey可以被其他非Character的Actor类型复用),我们直接在发消息前UpCast一下即可,提前做一个转换。

image-20230322202539766

到此问题解决。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!