Unity物体骨骼换装系统

Unity的换装系统是为了优化Unity资源,增加游戏乐趣,换装有两种,一种是增添式换装,比如给人物加个武器,装备翅膀等等,另外一种就是下面我要说的更新式换装,比如更换皮肤,更换武器,更换装备等等,换装还是很常见的功能,也是比较重要的知识点,那么,先看下代码吧:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AvatarSystem : MonoBehaviour
{
    public GameObject targetPlayer;
    public GameObject templatePlayer;

    public Transform targetTrans;
    public Transform templateTrans;

    //保存部位名称,编号和部位位置信息
    public Dictionary<string, Dictionary<string, Transform>> data = new Dictionary<string, Dictionary<string, Transform>>();
    //保存带有蒙皮渲染组件的部位名称和对应的蒙皮网格渲染组件
    public Dictionary<string, SkinnedMeshRenderer> partSMR = new Dictionary<string, SkinnedMeshRenderer>();

    //目标骨骼位置信息
    public Transform[] targetBones;

    //换装
    public string[,] avatarstr1 = new string[,] { { "coat", "001" }, { "hair", "001" }, { "pant", "001" }, { "hand", "003" }, { "foot", "003" }, { "head", "003" } };


    public void Start()
    {
        InsTemplatePlayer();
        InsTargetPlayer(2f);
        SaveData(templatePlayer);
        targetBones = targetPlayer.GetComponentsInChildren<Transform>();
        Change();
    }

    /// <summary>
    /// 实例化目标物体
    /// </summary>
    public void InsTargetPlayer(float pos_x)
    {
        targetPlayer = Instantiate(Resources.Load("targetmodel") as GameObject);
        targetTrans = targetPlayer.transform;
      
        targetPlayer.transform.position = new Vector3(pos_x, 0, 0);
    }
    /// <summary>
    /// 实例化模板物体
    /// </summary>
    public void InsTemplatePlayer()
    {
        templatePlayer = Instantiate(Resources.Load("FemaleAvatar") as GameObject);
        templateTrans = templatePlayer.transform;
      
        //因为这里我们不需要模板显示,只是需要模板信息,所以可以选择关闭模板的活跃
        templatePlayer.SetActive(false);
    }

    /// <summary>
    /// 保存模板里有蒙皮渲染组件的物体数据
    /// </summary>
    public void SaveData(GameObject template)
    {
        //首先清空原有数据
        data.Clear();
        partSMR.Clear();

        if (template == null)
            return;

        SkinnedMeshRenderer[] smrs = template.GetComponentsInChildren<SkinnedMeshRenderer>();
        
        foreach (SkinnedMeshRenderer smr in smrs)
        {
            string[] names = smr.name.Split('-');
           
            if (!data.ContainsKey(names[0]))
            {
                //print(names[0]);
                data.Add(names[0], new Dictionary<string, Transform>());
                GameObject obj = new GameObject();
                obj.AddComponent<SkinnedMeshRenderer>();
                obj.name = names[0];
                obj.transform.parent = targetPlayer.transform;
                obj.transform.position = smr.gameObject.transform.position;
                
                partSMR.Add(obj.name, obj.GetComponent<SkinnedMeshRenderer>());
                
            }//print(data[names[0]]);
                data[names[0]].Add(names[1], smr.transform);
           
        }
    }

    /// <summary>
    /// 换装(可以更换每个部位的信息)
    /// </summary>
    /// <param name="part">部位</param>
    /// <param name="ID">编号</param>
    public void ReLoading(string part,string ID)
    {
        SkinnedMeshRenderer smrs = data[part][ID].GetComponent<SkinnedMeshRenderer>();
        List<Transform> bones = new List<Transform>();
        foreach (Transform smr in smrs.bones)
        {
            foreach (Transform targetBone in targetBones)
            {
                if (targetBone.name == smr.name)
                {
                    bones.Add(targetBone);
                    print(targetBone.name +"     "+ targetBone);
                    break; 
                }
            }
        }
        partSMR[part].sharedMesh = smrs.sharedMesh;
        partSMR[part].materials = smrs.materials;
        partSMR[part].bones = bones.ToArray();
    }


    public void Change()
    {
        int count = avatarstr1.GetLength(0);
        for (int i = 0; i < count; i++)
        {
            ReLoading(avatarstr1[i, 0], avatarstr1[i, 1]);
        }
    }
}

上面的脚本就是一个简单的更新式换装脚本,更新式换装脚本的思路是,首先建立一个模板,然后建立一个和模板的骨骼列表一样的物体,但是除了骨骼列表之外别的什么都没有,然后,将模板和目标都实例化出来,之后取的模板的模型Mesh信息,根据信息给目标添加模型Mesh,添加之后需要给模型Mesh上网格,材质以及让模型Mesh和骨骼列表之间关联起来,这里注意一个点,用这种方法的时候,模型Mesh的骨骼列表不可以直接进行赋值,需要有个集合将模板的模型Mesh上面的骨骼列表保存起来然后把这个集合赋值给目标模型Mesh的骨骼列表,模型Mesh的网格,材质球是可以直接进行赋值的。

 

要做模型换装,程序就得和美术提前商量好,每个部位的名称,编号一定要做好,不然后期是个麻烦事,还得一个一个的找。

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值