3.8 Spine 换装大家有什么好的方案吗?

目前 setSlotTexture 换装方案只支持单纹理的换装,对于换装纹理数量少的情况还是很方便的,但是
纹理过多时就有点鸡肋了,大量的散图肯定是接受不了的,如果能支持 SpriteFrame 的话会更加通用一点,大家有什么好的方案吗?

1赞

用setSlotTexture换装以后,切换一些动画,会导致局部换装的位置错乱,像是位移了,有遇到的吗?

同样遇到,求大神给思路或者官方解决

我现在用污染的方式做,不污染的暂时没有解决方案

求思路,在laya3.2卡了一周了。

3.8查了一圈资料,好像只有setSlotTexture方式了。我们使用的外部贴图整个替换,比如一张图片上有hat、body等slot,相当于多调用几次setSlotTexture,由于这样比较麻烦,就在c++层扩展了个方法,一次性传入slots,同时更新。
原版setSlotTexture会更改图片的size和uv信息,这里直接去掉这部分代码就可以实现外部图片整个替换了。

static bool js_spine_SkeletonRenderer_replaceSlotsTex(se::State& s){
    const auto& args = s.args();
    spine::SkeletonRenderer *skeleton = SE_THIS_OBJECT<spine::SkeletonRenderer>(s);

    se::Object* obj = args[0].toObject();
    uint32_t length = 0;
    obj->getArrayLength(&length);
    std::vector<std::string> array;  // 用于保存解析后的字符串
    for (uint32_t i = 0; i < length; i++) {
        se::Value element;
        if (obj->getArrayElement(i, &element) && element.isString()) {
            array.push_back(element.toString());  // 将每个JS字符串转换为C++字符串
        }
    }

    cc::Texture2D *tex2d = nullptr;
    seval_to_native_ptr(args[1], &tex2d);
    SE_PRECONDITION2(nullptr == tex2d, false, "Error processing arguments texture");
    middleware::Texture2D *middlewareTexture = new middleware::Texture2D();
    middlewareTexture->addRef();
    middlewareTexture->setRealTexture(tex2d);

    for (const auto& str : array) {
        auto slot = skeleton->findSlot(str.c_str());
        if(!slot) continue;
        auto attachment = slot->getAttachment();
        if (!attachment) continue;

        spine::AttachmentVertices *attachmentVertices = nullptr;
        if (attachment->getRTTI().isExactly(spine::RegionAttachment::rtti)) {
            auto region = static_cast<spine::RegionAttachment *>(attachment);
            attachmentVertices = static_cast<spine::AttachmentVertices *>(region->getRendererObject());
        }
        if (!attachmentVertices) continue;
        if (attachmentVertices->_texture) attachmentVertices->_texture->release();
        attachmentVertices->_texture = middlewareTexture;
    }
    return true;
}
SE_BIND_FUNC(js_spine_SkeletonRenderer_replaceSlotsTex)

在jsb_spine_manual.cpp文件中绑定下方法,然后在ts中直接调用

sp.Skeleton.prototype.replaceSlotsTex = function(names: Array<string>, tex: Texture2D){
    if(this._nativeSkeleton)
        this._nativeSkeleton.replaceSlotsTex(names, tex);
}
const ske = this.node.getComponent(sp.Skeleton);
ske.replaceSlotsTex(['body', 'hat'], this.tex)

需要注意的是在ts层要保持this.tex图片的引用,防止被回收

_nativeSkeleton怎么获取 :grinning:

_nativeSkeleton是存在的,是engine-adapter.js文件中的字段。(sp.Skeleton组件调用原生方法是在这里实现的)

jsb_spine_manual.zip (5.3 KB)
传下jsb_spine_manual.cpp文件吧(creator3.8.3)
实现思路就是整个替换spine图片,然后不修改替换后slot的size和uv信息,这样就不会错乱显示了

谢谢!我研究一下

大佬,请问你们在spine做动画的时候,会不会出现换装掉了变成原始的spine装扮

是用了attach操作吧?附加操作会重置skeletonData

做动作之前用了setSlotTexture,这样会有影响吗?

setAnimation之前setSlotTexture也不会影响换装,只有attach会重置,我们这边的处理是把所有的附加操作都去掉,换成显示隐藏或者通过设置透明度

官方不是有个demo吧。外部换装,图集换装的可以借鉴一下论坛有些帖子

我这的spine一些slot里为了效果带了mesh,换装后做动作就会丢失。现在在考虑要不要换回3.7的spine

我这试了一下,并没有丢失动作,用的3.8.4的版本

动作不会丢失,但是带了mesh的换装会重置成原始spine的装扮

网页版我这里没什么问题,就是打包成安卓和ios会出问题

我是打包的Windows测试的,没遇到这个问题,确定动画里面没有用到attach 附加操作吗?已知的是用了附加就会重置SkeletonData