调用Spine的Skin相关函数会在Android中闪退

  • Creator 版本: v3.0

  • 目标平台: Android

  • 重现方式:
    使用mix-and-match的骨骼动画,然后调用如下代码,在Android机器会重现。
    onFaceChange(event:Event, customEventData:string){
    //console.log(“click button.”);

      const skFace = this.getFaceSkeleton();
      if(skFace){
          const skeletonData = skFace.skeletonData.getRuntimeData();
          const fulls = ["boy", "girl", "girl-blue-cape", "girl-spring-dress"];
          //
          const boySkin = this.getSkinByName(skeletonData.skins,
              "full-skins/" + fulls[0|(Math.random() * fulls.length)]);
          if(boySkin) {
              skFace.setSlotsToSetupPose();
              //console.log(skFace.setSkin);
    
              const boy = new sp.spine.Skin("npc_boy");
              boy.copySkin(boySkin);  // 在这里就会出错了。
              skFace.setSkin(boy);
          }
      }
    

    }

  • 首个报错:
    2021-03-18 10:33:22.170 7249-7278/com.cocos.android A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4030508040355 in tid 7278 (Thread-2), pid 7249 (m.cocos.android)
    2021-03-18 10:33:22.335 7417-7417/? A/DEBUG: Process name is com.cocos.android, not key_process
    2021-03-18 10:33:22.336 7417-7417/? A/DEBUG: pid: 7249, tid: 7278, name: Thread-2 >>> com.cocos.android <<<
    2021-03-18 10:33:22.359 7417-7417/? A/DEBUG: #00 pc 00000000010e2bb0 /data/app/com.cocos.android-Vd5kXcRbK0etz7Hsok6Yrg==/lib/arm64/libcocos.so (spine::Vectorspine::BoneData*::contains(spine::BoneData* const&)+32) (BuildId: ba670c31feb5df7ec04b9a8e815fe3687f456c49)
    2021-03-18 10:33:22.359 7417-7417/? A/DEBUG: #01 pc 00000000010e2cf0 /data/app/com.cocos.android-Vd5kXcRbK0etz7Hsok6Yrg==/lib/arm64/libcocos.so (spine::Skin::copySkin(spine::Skin*)+144) (BuildId: ba670c31feb5df7ec04b9a8e815fe3687f456c49)

另外有一个建议, Creator里的Skeleton提供的setSkin只支持string作为参数。

这个API对于换装类游戏, 根本没用。 肯定是多个Skin根据配置动态能组合的,像现在这个setSkin只支持预设的几个Skin, 没办法用。 我进行了一些修改, 在Web上可以跑起来了,但native上是不行的。
看jsb的代码,是支持两种类型的传参的。 建议支持。
/**

  • @method setSkin
    • @param {String|spine.Skin} skinName
      */
      public setSkin (skinName: string|spine.Skin) {
      if (this._skeleton) {
      if (typeof skinName === ‘string’) this._skeleton.setSkinByName(skinName);
      else this._skeleton.setSkin(skinName);
      this._skeleton.setSlotsToSetupPose();
      }
      this.invalidAnimationCache();
      }

抱歉, 在原生中Skin类是抽象类, 在ts层无法通过new的方式构造. 另外感谢你的建议, 我们会探讨并改进此类问题.

谢谢。 预计多久可以有结果?

预计最快放在3.1版本中改进此问题.

谢谢。辛苦了!

请问只要将Skin从spine.ini移出abstract_classes就可以了吗? 我试了一下, 出现字符串类型转换的错误。

com.cocos.android A/libc: D:/game/CocosDashboard_1.0.11/resources/.editors/Creator/3.0.0/resources/resources/3d/cocos2d-x-lite/cocos/bindings/jswrapper/Value.cpp:436: const std::string &se::Value::toString() const: assertion “_type == Type::String” failed

2021-03-26 16:40:45.243 22320-22320/com.cocos.android D/ColorViewRootUtil: nav gesture mode swipeFromBottom ignore false downX 125 downY 276 mScreenHeight 2340 mScreenWidth 1080 mStatusBarHeight 54 globalScale 1.125 nav mode 2 event
MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=125.0, y[0]=276.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=85321952, downTime=85321952, deviceId=6, source=0x1002, displayId=0 } rotation 0
2021-03-26 16:40:45.293 22320-22358/com.cocos.android E/jswrapper: Can not convert type ???
- [[ N5spine6StringE ]]
2021-03-26 16:40:45.293 22320-22358/com.cocos.android E/jswrapper: jsb: ERROR: File D:/game/CocosDashboard_1.0.11/resources/.editors/Creator/3.0.0/resources/resources/3d/cocos2d-x-lite/cocos/bindings/auto/jsb_spine_auto.cpp: Line: 11245, Function: js_spine_Skin_constructor
2021-03-26 16:40:45.293 22320-22358/com.cocos.android E/jswrapper: js_spine_Skin_constructor : Error processing arguments
2021-03-26 16:40:45.293 22320-22358/com.cocos.android E/jswrapper: [ERROR] Failed to invoke js_spine_Skin_constructor, location: D:/game/CocosDashboard_1.0.11/resources/.editors/Creator/3.0.0/resources/resources/3d/cocos2d-x-lite/cocos/bindings/auto/jsb_spine_auto.cpp:11251

--------- beginning of crash

2021-03-26 16:40:45.294 22320-22358/com.cocos.android A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4030508040355 in tid 22358 (Thread-2), pid 22320 (m.cocos.android)

我修改了一下代码重新生成的jsb代码:
–jsb_spine_auto.cpp
static bool js_spine_SkeletonRenderer_setSkin(se::State& s)
{
CC_UNUSED bool ok = true;
spine::SkeletonRenderer* cobj = SE_THIS_OBJECTspine::SkeletonRenderer(s);
SE_PRECONDITION2( cobj, false, “js_spine_SkeletonRenderer_setSkin : Invalid Native Object”);
const auto& args = s.args();
size_t argc = args.size();
do {
if (argc == 1) {
HolderType<const char*, false> arg0 = {};

        ok &= sevalue_to_native(args[0], &arg0, s.thisObject());
        if (!ok) { ok = true; break; }
        cobj->setSkin(arg0.value());
        return true;
    }
} while(false);

do {
    if (argc == 1) {
        HolderType<std::string, true> arg0 = {};  //出错在这里

        ok &= sevalue_to_native(args[0], &arg0, s.thisObject());
        if (!ok) { ok = true; break; }
        cobj->setSkin(arg0.value());
        return true;
    }
} while(false);

do {
    if (argc == 1) {
        HolderType<spine::Skin*, false> arg0 = {};

        ok &= sevalue_to_native(args[0], &arg0, s.thisObject());
        if (!ok) { ok = true; break; }
        cobj->setSkin(arg0.value());
        return true;
    }
} while(false);

SE_REPORT_ERROR("wrong number of arguments: %d", (int)argc);
return false;

}

– SkeletonRenderer.h
void setSkin(const std::string &skinName);
/** @param skin May be 0 for no skin./
void setSkin(const char skinName);
/
* @param newSkin May be NULL.
/
void setSkin(Skin *newSkin);

– SkeletonRenderer.cpp
void SkeletonRenderer::setSkin(Skin *newSkin) {
if (_skeleton) {
_skeleton->setSkin(newSkin);
_skeleton->setSlotsToSetupPose();
}
}

有三个方法是要在C++里新增的 getAttachments() getEntryName() getEntrySlot(). 具体实现有问题的话可以私信我 我这边有用户解决了这类问题

请问。你们DESTROY之后 SPINE的纹理信息能从 gpu mem中清理掉吗?

这个问题我在2.4.6也遇到。直接闪退。请问你解决了吗?

問下,目前有哪個版本已經解決這項問題了嗎?最近想給專案升級引擎