[]分享:Dragonbones/Spine的换肤操作

       目前LayaAir下支持龙骨的局部换肤(根据插槽索引换肤、根据插槽name换肤、纹理换肤、网格换肤)、全局换肤
       需注意:
     1、Dragonbones不支持全局换肤,Spine支持全局换肤
     2、使用到IK和网格的动画需要开启WebGL,否则可能会出现皮肤丢失的情况
     3、Dragonbones与spine的接口是一样的,除第一种情况外,下面的示例通用于Dragonbones和spine
 
下面我们就一个个来看下如何使用换肤的方法
1、局部换肤-根据插槽索引换肤,对应Skeleton类下的replaceSlotSkinByIndex方法
我们从创建动画开始,一步步来操作
    1-1 打开dragonbones官方示例Dragon动画,并准备好一张皮肤,这次我打算替换head头部,开发者也可以选择自己喜欢的部位
打开的动画

111.png


准备好的替换head头部的皮肤head4.png,(*^__^*) 嘻嘻……随便找来一张

555.png


    1-2 将准备好的皮肤head4.png放到项目的library文件夹下(library文件夹是Dragonbones的资源存放文件夹)

222.png


1-3 在Dragonbones编辑器舞台上点击小龙的头部,在场景树面板中可以看到我们选中的head皮肤,在资源面板中找到head4.png并拖拽到head皮肤上,这样就会自动生成head插槽下以及2个可选的皮肤纹理了,如下

666.png


放置OK显示如下,点击插槽下的皮肤前的小圆点,就可以自由切换皮肤了

777.png

 
    1-4 切换皮肤至原始状态,选中parts/head皮肤,然后导出动画(点击菜单->文件->导出)

888.png

注意:
    1、龙骨版本在4.6至4.9版本之间,数据版本选择4.5,输出比例为1,配套纹理选择纹理集,导出类型为Dragonbones,选项是固定好的,不可随意更改
 
   1-5 打开LayaAirIDE,菜单栏->工具->龙骨导出工具,将Dragonbones工具导出的龙骨资源文件夹拖拽到Air IDE龙骨导出工具上,进行一次转换

1212.png

注意:使用龙骨转换工具时,龙骨文件夹的命名要跟动画的命名保持一致,譬如这次我的文件夹名为DragonDragon,那么DragonDragon文件夹下必然同样有个DragonDragon.json,两者命名不可有差异,否则转换过程中会导致报错提示

131313.png

红色框内的文件为原始导出文件,其他2个文件是龙骨转换工具转换后的2个文件
    1-6 代码编辑,已经详细解释每步代码的含义,此处不累述
package 
{
import laya.ani.bone.Skeleton;
import laya.ani.bone.Templet;
import laya.display.Sprite;
import laya.display.Text;
import laya.events.Event;
import laya.utils.Browser;
import laya.utils.Stat;
import laya.webgl.WebGL;

public class LayaAirDemo
{
private var templete:Templet;//动画模板类
private var skeleton:Skeleton;//骨骼动画类
private var curNum:int=0;//curNum%2求余数,切换不同皮肤
public function LayaAirDemo()
{
Laya.init(Browser.width,Browser.height,WebGL);//初始化LayaAir引擎
Stat.show();//舞台左上角显示帧频信息
Laya.stage.bgColor='#EEFFCC';//设置舞台背景色
Laya.stage.alignH='center';//水平居中对齐
Laya.stage.alignV='middle';//垂直居中对齐
Laya.stage.scaleMode='showall';//缩放模式
Laya.stage.screenMode='horizontal';//竖屏显示

templete=new Templet();//实例化动画模板
templete.loadAni('DragonDragon/DragonDragon.sk');//加载龙骨动画数据
templete.on(Event.COMPLETE,this,onPleteComed);//数据解析完成后的调度事件。
}

private function onPleteComed():void
{
skeleton=templete.buildArmature(1);//创建动画,类型:1 支持换装
skeleton.pos(150,250);//动画位置
skeleton.play(0,true);//动画播放,从0帧开始,不断循环播放
skeleton.scale(0.5,0.5);//动画缩放为原始状态的二分之一
Laya.stage.addChild(skeleton);//添加动画至舞台,这时候运行,动画已经可以播放了

createButton();//创建一个按钮,用来切换皮肤使用
}

private function createButton():void
{
var btn:Sprite=new Sprite();//绘制一个红色矩形按钮
btn.graphics.drawRect(0,0,150,30,'#FF0000');
btn.pos(10,430);
btn.size(150,30);//sprite如果要触发鼠标事件,务必设置好size,也就是鼠标的相应区域
btn.on(Event.CLICK,this,onChangeSkin);
Laya.stage.addChild(btn);

var text:Text=new Text();
text.text='切换皮肤';
text.fontSize=20;
btn.addChild(text);
text.pos(35,5);

}

private function onChangeSkin():void
{
curNum++;
if(curNum%2!=0)
{
skeleton.replaceSlotSkinByIndex('head',0,1);//head插槽下,让索引为1的皮肤替换索引为0的皮肤
}
else
{
skeleton.replaceSlotSkinByIndex('head',0,0);//head插槽下,让索引为0的皮肤替换索引为0的皮肤,也就是原始状态
}
}
}
}
2、局部换肤-根据插槽name换肤,对应Skeleton类下的replaceSlotSkinName方法
依然是以上代码,我们只需要修改下onChangeSkin函数即可,如下
private function onChangeSkin():void
{
curNum++;
if(curNum%2!=0)
{
skeleton.replaceSlotSkinName('head','parts/head','head4');//head插槽下,让head4皮肤替换parts/head皮肤
}
else
{
skeleton.replaceSlotSkinName('head','parts/head','parts/head');//head插槽下,让parts/head皮肤替换parts/head皮肤
}
}
3、局部换肤-外部纹理换肤,对应Skeleton类下的setSlotSkin方法
     外部纹理换肤,顾名思义,就是采用外部纹理资源加载的方式,替换插槽处的皮肤,不再是龙骨的内部换肤了,那么我们就准备好将一张准备替换皮肤的图片放到我们的资源目录下
 3-1 将准备好的图片放置项目资源目录下,并预加载资源,获取texture
准备好的图片head3.png

head3.png

放置资源目录下
aaa.png

获取texture
		Laya.loader.load('head3.png',Handler.create(this,onTextureLoaded));
}
private var texture:Texture;
private function onTextureLoaded():void
{
texture=Loader.getRes('head3.png');
}
整体代码如下
package 
{
import laya.ani.bone.Skeleton;
import laya.ani.bone.Templet;
import laya.display.Sprite;
import laya.display.Text;
import laya.events.Event;
import laya.net.Loader;
import laya.resource.Texture;
import laya.utils.Browser;
import laya.utils.Handler;
import laya.utils.Stat;
import laya.webgl.WebGL;

public class LayaAirDemo
{
private var templete:Templet;//动画模板类
private var skeleton:Skeleton;//骨骼动画类
private var curNum:int=0;//curNum%2求余数,切换不同皮肤
public function LayaAirDemo()
{
Laya.init(Browser.width,Browser.height,WebGL);//初始化LayaAir引擎
Stat.show();//舞台左上角显示帧频信息
Laya.stage.bgColor='#EEFFCC';//设置舞台背景色
Laya.stage.alignH='center';//水平居中对齐
Laya.stage.alignV='middle';//垂直居中对齐
Laya.stage.scaleMode='showall';//缩放模式
Laya.stage.screenMode='horizontal';//竖屏显示

templete=new Templet();//实例化动画模板
templete.loadAni('DragonDragon/DragonDragon.sk');//加载龙骨动画数据
templete.on(Event.COMPLETE,this,onPleteComed);//数据解析完成后的调度事件。

Laya.loader.load('head3.png',Handler.create(this,onTextureLoaded));
}
private var texture:Texture;
private function onTextureLoaded():void
{
texture=Loader.getRes('head3.png');
}

private function onPleteComed():void
{
skeleton=templete.buildArmature(1);//创建动画,类型:1 支持换装
skeleton.pos(150,250);//动画位置
skeleton.play(0,true);//动画播放,从0帧开始,不断循环播放
skeleton.scale(0.5,0.5);//动画缩放为原始状态的二分之一
Laya.stage.addChild(skeleton);//添加动画至舞台,这时候运行,动画已经可以播放了

createButton();//创建一个按钮,用来切换皮肤使用
}

private function createButton():void
{
var btn:Sprite=new Sprite();//绘制一个红色矩形按钮
btn.graphics.drawRect(0,0,150,30,'#FF0000');
btn.pos(10,430);
btn.size(150,30);//sprite如果要触发鼠标事件,务必设置好size,也就是鼠标的相应区域
btn.on(Event.CLICK,this,onChangeSkin);
Laya.stage.addChild(btn);

var text:Text=new Text();
text.text='切换皮肤';
text.fontSize=20;
btn.addChild(text);
text.pos(35,5);

}

private function onChangeSkin():void
{
curNum++;
skeleton.setSlotSkin('head',texture);//使用texture纹理替换head插槽处的皮肤
}
}
}
发布结果如下:
未点击按钮之前的状态

bb.png

点击切换皮肤按钮后的状态

cc.png

 
注意:
      1、setSlotSkin同时也是网格部位换肤的方法,目前只有setSlotSkin支持带有网格部位的换肤,用法同上所述,其他2种方式replaceSlotSkinByIndex与replaceSlotSkinName不支持带有网格部位的换肤操作
     2、全局换肤目前只有spine支持,具体示例,大家可以参考下官方示例:骨骼动画-换肤
已邀请:

Monica - 知识达人

赞同来自:

赞~\(≧▽≦)/~

TsubasaYeung

赞同来自:

给力,现在项目里用的是 Spine 

沧海一粟

赞同来自:

MarkMark

云龙

赞同来自:

3、局部换肤-外部纹理换肤,对应Skeleton类下的setSlotSkin方法

用的这个方法,发现个问题,新图片和原来图片大小不同,结果换肤之后新图片被拉伸变形了。请问这个问题怎么解决?

Not a Function

赞同来自:

请教一下,UI界面拖入的骨骼动画怎么修改动画模式
 

赞同来自:

请求一下,为什么我用setSlotSkin方法,没有任何反应,调用setSlotSkin之后也调用了play了

1599460355用户

赞同来自:

同上,有解决办法么
let str = 'res/game/hair.png';
Laya.loader.load(str, Laya.Handler.create(this, () => {
let texture = Laya.loader.getRes(str);
this._sk.setSlotSkin('wHair', texture)
}))
没反应啊

小火火

赞同来自:

不知道是不是typescript改得有点大,上边代码要改很多才能运行,我现在把demo发出,希望对各位有帮助,也怕我回头把代码搞丢了

要回复问题请先

商务合作
商务合作