Unity动态换装之Spine换装

本文详细介绍了Unity中利用Spine实现动态角色换装的原理、理论分析、Spine源代码修改以及换装步骤,重点在于如何进行局部换装,通过对Spine数据的解析和映射,实现在游戏运行时的动态换装效果。
摘要由CSDN通过智能技术生成

Unity动态换装之Spine换装

注:转载请注明转载,并附原链接 http://www.cnblogs.com/liaoguipeng/p/5867510.html 燕双飞情侣

一、动态换装原理

  1. 换装,无非就是对模型的网格,或者贴图进行针对性置换;
  2. 对于3D局部换装,我们可能需要单独换模型和贴图,也可能只需要单独置换贴图即可
  3. 对与Spine2D角色换装,我们基本上只需要针对性置换贴图,也就是Slot插槽上对应的附着物Attachment即可
  4. QQ图片20160913113901

 

 

 

 

 

 

 

 

 


 

二、换装理论分析

  1. Spine目前提供的换装是整体换装,也就是动画那边做好几套Skin,需要哪套直接调用SKeletonAnimation中的InitialSkin进行置换就行了,这个看起来很简单嘛。
  2. 但是,如果我们需要局部换装,难道让动画把每个局部都单独列出来,比如我们一个角色10套
  3. 皮肤,每套皮肤有对于10个位置可以进行任意更换,那么动画岂不是要做10! = 3 628 800 套皮肤?计算机装得下?程序调用逻辑不会出错?这么看来,这个方案不科学。
  4. 那么,我们有没有一种方法,可以实现到局部换装?于是,开始针对Spine导出文件进行分析;Spine可到处二进制和Json数据文件,为了方便分析,我们这次使用Json文件进行分析:

    image
    Spine导出文件有Png,Json和Altas,Png只是静态贴图,我们暂且可以忽略;那么我们观察Altas,截取部分数据:

     
          
    1 Lead.png 2 size: 2048 , 128 3 format: RGBA8888 4 filter: Linear,Linear 5 repeat: none 6 L_hand000 7 rotate: true 8 xy: 790 , 69 9 size: 57 , 87 10 orig: 57 , 87 11 offset: 0 , 0 12 index: - 1 13 L_leg000 14 rotate: true 15 xy: 1354 , 93 16 size: 33 , 91 17 orig: 33 , 91 18 offset: 0 , 0 19 index: - 1
     

    并没有多大作用…  那么我们在看看另一个Json文件,截取部分信息:

    套装1: clothing001部分插槽和贴图数据

     
          
    1 "clothing001": { 2 // 此处省略一大堆动画数据和插槽数据,我们目前看套装1的武器 weapon_C部分 3 "hair_C" : { 4 "hair_C": { "name": "clothing001/hair001", "x": -14.38, "y": -11.92, "rotation": -93.18, "width": 100, "height": 78 } 5 }, 6 "shield_C": { 7 "shield_C" : { "name": "clothing001/shield001", "x": 20.78, "y": -0.75, "rotation": -11.65, "width": 62, "height": 77 } 8 }, 9 "weapon_C": { 10 "weapon_C" : { "name": "clothing001/weapon001", "x": 50.69, "y": -1.75, "rotation": -153.42, "width": 142, "height": 87 } 11 } 12 },



    套装2:clothing002部分插槽和贴图数据

     
          
    1 "clothing002": { 2 "hair_C" : { 3 "hair_C": { "name": "cloting002/hair002", "x": 15.26, "y": -9.01, "rotation": -93.18, "width": 84, "height": 63 } 4 }, 5 "shield_C": { 6 "shield_C" : { "name": "cloting002/shield002", "x": 20.78, "y": -0.75, "rotation": 92.7, "width": 80, "height": 84 } 7 }, 8 "weapon_C": { 9 "weapon_C" : { "name": "cloting002/weapon002", "x": 74.02, "y": 0.77, "rotation": -153.42, "width": 190, "height": 108 } 10 } 11 } 12 },


    通过数据对比,我们可以发现套装数据结构一致,只是内部存储的数据不同,那么我们尝试将clothing001套装和clothing002套装内的其中一部分数据进行对调,比如我们对调“weapon_C”的所有数据,把文件导入Unity会发生什么呢?

    对调前: 
                 image                image
                              “cloth001”                                              “cloth002”

    对调后:
                image                  image
                              “cloth001”                                              “cloth002”

    预料之中,那么局部换装的实现,就应该不成问题了,那么我们回到代码层开始分析.

三、Spine底层库源代码分析

  1. 我们先观察Spine提供的整套换装源代码:

    image
     
          
    1 namespace Spine.Unity { 2 [ExecuteInEditMode, RequireComponent( typeof (CanvasRenderer), typeof (RectTransform)), DisallowMultipleComponent] 3 [AddComponentMenu( " Spine/SkeletonGraphic (Unity UI Canvas) " )] 4 public class SkeletonGraphic : MaskableGraphic, ISkeletonComponent, IAnimationStateComponent, ISkeletonAnimation { 5 6 #region Inspector 7 public SkeletonDataAsset skeletonDataAsset; 8 public SkeletonDataAsset SkeletonDataAsset { get { return skeletonDataAsset; } } 9 10 [SpineSkin(dataField: " skeletonDataAsset " )] 11 public string initialSkinName = " default " ; 12 13 [SpineAnimation(dataField: " skeletonDataAsset " )] 14 public string startingAnimation; 15 public bool startingLoop; 16 public float timeScale = 1f; 17 public bool freeze;


    根据initialSkinName我们继续往下查找
     
          
    1 // Set the initial Skin and Animation 2 if ( ! string .IsNullOrEmpty(initialSkinName)) 3 skeleton.SetSkin(initialSkinName); 4


     
          
    1 /// <summary> Sets a skin by name (see SetSkin). </summary> 2 public void SetSkin (String skinName) { 3 Skin skin = data.FindSkin(skinName); 4 if (skin == null ) throw new ArgumentException( " Skin not found: " + skinName, " skinName " ); 5 SetSkin(skin); 6 }




     
          
    1 /// <summary> Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default 2 /// skin}. Attachmentsfrom the new skin are attached if the corresponding attachment from the old skin was attached. If 3 /// there was no old skin, each slot's setup mode attachment is attached from the new skin. </summary> 4 /// <param name="newSkin"> May be null. </param> 5 public void SetSkin (Skin newSkin) { 6 if (newSkin != null ) { 7 if (skin != null ) 8 newSkin.AttachAll( this , skin); 9 else { 10 ExposedList < Slot > slots = this .slots; 11 for ( int i = 0 , n = slots.Count; i < n; i ++ ) { 12 Slot slot = slots.Items[i]; 13 String name = slot.data.attachmentName; 14 if (name != null ) { 15 Attachment attachment = newSkin.GetAttachment(i, name); 16 if (attachment != null ) slot.Attachment = attachment; 17 } 18 } 19 } 20 } 21 skin = newSkin; 22 }



    就是这个函数,SetSkin(Skin newSkin),通过传入Skin套装数据,遍历所有对应的骨骼,更新骨骼上对应的贴图数据。
  2. 那么,思路就来了,我们Spine进行局部换装,不也就是更新某个SKin中某个Slot上对应的Attachment数据么?
    因此,想想现实世界中的拼图游戏,假设我们有N块整体拼图(数据库Skin),整体拼图中对于的每一块小拼图碎片(Attachment),都能在其他N-1块整体配图(数据库Skin)找到唯一一块相同规格(相同的Slot)但是画面不同的拼图碎片(Attachment),我们需要一个动态的拼图底板(动态Skin来容纳我们的拼图碎片(Attachment),而要想拼一块完整的拼图,我们只需要从N块整体拼图(数据库Skin)中,任意取对应规格(Slot)的配图碎片(Attachment)组装到动态的拼图底板(动态Skin)中,全部Slot组装完成以后,我们就可以得到一幅完整又与其他表现不同的拼图。

        
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity中实现人物换装功能可以通过以下几个步骤来实现。 首先,将人物模型拆分为头、身体、手臂、腿、武器等部分。这样可以实现每个部位的独立建模和贴图,为后续的换装提供基础。[1] 其次,可以使用替换蒙皮网格的方法来实现简单的换装效果。这意味着可以替换模型换装部位的GameObject,或直接替换蒙皮网格。这种方法适用于合并模型网格的情况,它不会关心替换部位是否属于原始角色的一部分。同时,如果需要替换的部位有多个配件拥有独立的网格和贴图,则此方法也适用。 然后,可以考虑合并所有蒙皮网格,以降低游戏的Draw Call数量。这涉及到重新计算UV,合并贴图和材质。这种复杂的实现可以通过以下步骤来完成:替换蒙皮网格或替换换装部位的GameObject,然后合并所有蒙皮网格,刷新骨骼,附加材质,合并贴图,并重新计算UV。这样可以实现更复杂的换装效果。 最后,根据需要可以实现实时时装和各种搭配效果。这可以通过动态换装的方式来实现,利用avatar来实现装备与人物分离的效果。 综上所述,Unity中可以通过拆分模型、替换蒙皮网格、合并网格和贴图、刷新骨骼、重新计算UV等方法来实现人物换装功能。这样可以实现自由换装、实时时装和各种搭配效果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [如何用Unity3D实现游戏中的角色换装?](https://blog.csdn.net/august5291/article/details/120259369)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [unity 3d换装SkinMeshRenderer](https://blog.csdn.net/kenkao/article/details/79928166)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值