unity人物换装

unity人物换装

人物换装算是游戏中的老梗了,为了美化游戏,为获取更好的游戏体验,很多游戏中可以实现人物换装,还可以给人物更换武器,还要翅膀什么的。总之,能在玩家在体验上 带来很好的效果。
先看下效果图。
这里写图片描述
这个就把一个人物的形象稍微改变了下。为游戏增加些乐趣。

人物的皮肤的制作

首先看下人物皮肤的制作,其实这里美术已经给制作几套模型,我们之给第一套人物模型添加上骨骼,后面的就皮肤都不添加上骨骼了。只有给其加上SkinnedMeshRenderer,且只给添加上一套SkinnedMeshRenderer,不能够添加重复了。

这里就可以去批量生成衣服的prefab了。最好的CreatePrefabInternal()函数就是一句自定义的制作prefab的函数了。

[MenuItem("GameObject/批量生成角色衣服Prefab", false, 0)]
    public static void GenerateBodyClothPrefab()
    {
        if (index >= 1)
        {
            ResetCreateNormalPrefabByFbxmane();
            return;
        }
        index++;
        GameObject[] objs = Selection.gameObjects;
        for (int index1 = 0; index1 < objs.Length; index1++)
        {
            GameObject obj = objs[index1];
            if (obj.GetComponent<SkinnedMeshRenderer>() == null)
            {
                SkinnedMeshRenderer[] skins = obj.GetComponentsInChildren<SkinnedMeshRenderer>();
                if (skins != null && skins.Length > 0)
                {
                    for (int i = 0; i < skins.Length; i++)
                    {
                        CreateSingleBodySkinPrefab(skins[i].gameObject);
                    }
                }
            }
            else
            {
                CreateSingleBodySkinPrefab(obj);
            }
        }
    }
 public static void CreateSingleBodySkinPrefab(GameObject skin)
    {
        if (skin == null) return;
        SkinBonesRecord boneRecord = skin.GetComponent<SkinBonesRecord>();
        if (boneRecord == null)
            boneRecord = skin.AddComponent<SkinBonesRecord>();
        boneRecord.RecordBoneNames();
        SkinnedMeshRenderer mesh = skin.GetComponent<SkinnedMeshRenderer>();
        mesh.receiveShadows = false;
        mesh.useLightProbes = false;
        mesh.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
        EditorUtility.SetDirty(skin);
        string prefabpath = tempPrefabFolderPath + skin.name + "skin.prefab";
        CreatePrefabInternal(skin, prefabpath);
    }

加载衣服模型

衣服的prefab制作好了,我们在游戏中将其的assetBundle加载进来。这里是通过ShowClothStyle的id将其加载进来的,如果为0的话,就卸载当前的衣服,否则就进去穿衣服的函数。

 public void ShowEquipsFashionCloth(int ShowClothStyle)
        {
            if (LoadConfigManager.ModelShowContainer.dic.ContainsKey(ShowClothStyle) == false)
            {
#if UNITY_EDITOR
                Debug.LogFormat("不存在时装{0}", ShowClothStyle);
#endif
                return;
            }
            #region 衣物模型生成
            if (ShowClothStyle != 0)
            {
                //更换
                if (ShowClothStyle != _lastClothStyle && ShowClothStyle != 0)
                {           characterGene.ChangeBodyCloth(ShowClothStyle, false);
                }
            }
            else
            {
                //脱下装备
                if (_lastClothStyle != 0)
                {
                    characterGene.RemoveBodyCloth();
                }
            }
            #endregion
            _lastClothStyle = ShowClothStyle;
        }

下面的函数会先将旧的衣服的id号保存起来,然后装备里面的号码更新为新的id号。

public void ChangeBodyCloth(int modelid, bool isNgui = false, System.Action doneact = null)
    { 
        int oldclothid = 0;
        if (equipsModelCache.ContainsKey("body"))
            oldclothid = equipsModelCache["body"];
        var model = LoadConfigManager.ModelShowContainer.GetModelShow(modelid);
        if (model == null)
        {
            return;
        }
        equipsModelCache["body"] = modelid;
        GameManager.assetBundleNew.StartCoroutine(_ChangeBodyCloth(modelid, isNgui,oldclothid, doneact));
    }

因为要在assetBundle里面加载,所有需要使用协程函数。

 private IEnumerator _ChangeBodyCloth(int clothid, bool isNgui, int oldClothid, System.Action doneact)
    {
        if (characterRoot == null)
        {
            Debug.Log("!!! character root is not exist");
            yield break;
        }
        bool isMapRelevant = true;
        if (isNgui)
            isMapRelevant = true;
        GameObject newskinobj = GameManager.objectCacheMgr.SpawnByModelStyle(CacheType.ResName_Model, clothid, true);
        if (newskinobj == null)
        {
            var abinfo = GameManager.assetBundleNew.CreateModelAB(clothid, false, true, isMapRelevant, isNgui);
            if (abinfo == null)
            {
                yield break;
            }
            while (!abinfo.IsDone)
                yield return null;

            newskinobj = abinfo.objInst as GameObject;
            if (isMapRelevant)
              //从缓存池里读取  AssetBundles.AssetBundleManagerNew.AddToMapRelDyUnloadAbInfos(abinfo, isMapRelevant);
            else
              //放入缓存里面  AssetBundles.ABLoadInfo.Release(abinfo);
            if (newskinobj == null)
            {
                yield break;
            }
        }
        if (destroy)
        {       GameManager.objectCacheMgr.CacheExsistGOToCachePool(5, clothid, "", newskinobj, false, false);
            yield break;
        }
        if (!equipsModelCache.ContainsKey("body") || equipsModelCache["body"] != clothid)
        {
#if UNITY_EDITOR
            Debug.LogWarning(clothid + "---download clothid is not cur clothid---- " + "body --" + equipsModelCache["body"]);
#endif
            GameManager.objectCacheMgr.CacheExsistGOToCachePool(5, clothid, "", newskinobj, false, false);
            yield break;
        }
        //共用一套总骨骼,但是需要更新信息,需要公用下载
        if (skins == null)
        {
            Debug.LogError("no skin");
            yield break;
        }
        SkinnedMeshRenderer newskin = newskinobj.GetComponent<SkinnedMeshRenderer>();
        SkinBonesRecord skinbonesRecord = newskinobj.GetComponent<SkinBonesRecord>();
        if (newskin == null)
        {
            Debug.LogError("new skin obj no skinnedmeshrender " + newskinobj.name);
            GameObject.Destroy(newskinobj);
            yield break;
        }
        if (skinbonesRecord == null)
        {
            Debug.LogError("new skin obj no SkinBonesRecord " + newskinobj.name);
            GameObject.Destroy(newskinobj);
            yield break;
        }
        List<Transform> bones = new List<Transform>(40);
        for (int i = 0; i < skinbonesRecord.BoneNames.Count; i++)
        {
            for (int j = 0; j < bonetrans.Length; j++)
            {
                if (boneNames[j] == skinbonesRecord.BoneNames[i])
                {
                    bones.Add(bonetrans[j]);
                    break;
                }
            }
        }
        if (normalRoot == null)
        {
            GameObject.Destroy(newskinobj);
            yield break;
        }
        if (newSkinMesh == null)
        {
            newSkinMesh = newskin;
            newskin.bones = bones.ToArray();
            newskinobj.transform.SetParent(normalRoot.transform);
            newskinobj.transform.localPosition = Vector3.zero;
            newskinobj.transform.localEulerAngles = new Vector3(-90, 0, 0);
            newskinobj.transform.localScale = Vector3.one;
            baseSkinMesh.gameObject.SetActive(false);
            newskinobj.SetActive(true);
        }
        else
        {
            newskin.bones = bones.ToArray();
            newskinobj.transform.SetParent(normalRoot.transform);
            newskinobj.transform.localPosition = Vector3.zero;
            newskinobj.transform.localEulerAngles = new Vector3(-90, 0, 0);
            newskinobj.transform.localScale = Vector3.one;
            baseSkinMesh.gameObject.SetActive(false);
            newskinobj.SetActive(true);
            if (oldClothid != 0)
                GameManager.objectCacheMgr.CacheExsistGOToCachePool(5, oldClothid, "", newSkinMesh.gameObject, false, false);
            else
                GameObject.DestroyImmediate(newSkinMesh.gameObject);
            newSkinMesh = newskin;
        }
        if (isNgui)
        {
            NGUITools.SetLayer(newSkinMesh.gameObject, (int)SceneLayer.NGui);
        }
        else
        {
            Util.SetObjectLayerWithTagFilter(charobtype, newSkinMesh.gameObject, Const.SceneTags_ModelEffect);
        }
        ChangeSkinShader();
        if (doneact != null)
            doneact();
    }
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
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 ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值