人物换装是动作类游戏必不可少的一个功能,本篇就介绍一个简易的换装功能,如要换装,人物身体肯定会拆分成几个部分,如头部,武器,身体等,每个部分都有一个SkinnedMeshRenderer组件,这个组件有三个重要元素,分别是bone(骨骼)、material(材质)、mesh(网格信息),根据这些进行蒙皮计算。若要实现换装,将待换部件的SkinnedMeshRenderer组件的信息替换原部件即可。本篇文章中的代码实现的功能为:角色的血量在高于某一个设定值的时候是正常衣服,否则换为破洞衣服。测试时将完整衣服与破洞衣服对应的.FBX拖拽到脚本即可,具体代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ChangeSkin : MonoBehaviour
{
[Header("破洞衣服")]
public GameObject lousyClothes;//破洞衣服
[Header("完整衣服")]
public GameObject fullClothes;//完整衣服
[Header("换装血量百分比")]
public float percent;//换装血量百分比
private Player _player;//人物控制脚本,存贮人物血量、ID等信息
private GameObject _clothes;//当前人物的衣服
private GameObject _flagClothes;//衣服换装标志
private List<Transform> _bones;//存储Skin合并后的骨骼引用
private GameObject _rootBone;//根骨骼
void Start ()
{
_player=transform.GetComponentInParent<Player>();
_rootBone = gameObject.transform.FindChildByName ("Bip001 Pelvis").gameObject;//根骨骼名字会不同
_bones = new List<Transform> ();
_clothes = fullClothes;
_flagClothes = _clothes;
ChangeSkinnedMesh ();
}
void Update()
{
//根据血量来控制人物所穿的衣服
if (_player.Life>_player.MaxLife*percent)
_clothes = fullClothes;
else
_clothes = lousyClothes;
//为避免每帧都调用ChangeSkinnedMesh()方法重构,仅当检测到衣服变化进行调用
if (_clothes.name!=_flagClothes.name) {
ChangeSkinnedMesh ();
_flagClothes=_clothes;
}
}
public void ChangeSkinnedMesh()
{
_bones.Clear ();
List<CombineInstance> combineInstances = new List<CombineInstance> ();
List<Material> materials = new List<Material> ();
Transform[] transforms = _rootBone.GetComponentsInChildren<Transform> (true);
if (_clothes==null )
return;
SkinnedMeshRenderer smr = _clothes.GetComponentInChildren<SkinnedMeshRenderer> ();
//将要更换衣服的SkinnedMeshRenderer组件上的信息记录保存下来
if (smr!=null) {
for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++) {
for (int j = 0; j < smr.bones.Length; j++) {
for (int index = 0; index < transforms.Length; index++) {
if (smr.bones [j].name.Equals (transforms [index].name)) {
_bones.Add (transforms [index]);
break;
}
}
}
CombineInstance ci = new CombineInstance ();
ci.mesh = smr.sharedMesh;
ci.subMeshIndex = sub;
combineInstances.Add (ci);
}
materials.AddRange (smr.sharedMaterials);
}
//将原来的SkinnedMeshRenderer删除,将更换信息的添加上去
SkinnedMeshRenderer oldSkin = GetComponent<SkinnedMeshRenderer> ();
if (oldSkin != null) {
GameObject.DestroyImmediate (oldSkin);
}
SkinnedMeshRenderer newSmr = gameObject.AddComponent<SkinnedMeshRenderer> ();
newSmr.sharedMesh = new Mesh ();
newSmr.sharedMesh.CombineMeshes (combineInstances.ToArray (), false, false);
newSmr.bones = _bones.ToArray ();
newSmr.rootBone = _rootBone.transform;
newSmr.materials = materials.ToArray ();
}
}
本篇博客参考博文:浅谈角色换装功能–Unity简单例子实现,有关更多换装详细介绍可进行查看。