Unity 角色换装SkinnedMeshRenderer

版权声明:转载请注明出处。 https://blog.csdn.net/QWBin/article/details/84170472

Unity 角色换装SkinnedMeshRenderer

这个资源来源于网上,写的确实不错,拿过来给大家分享下(便于大家理解做了简单的修改)下面还有连接可直接下载所有资源:

using UnityEngine;
using System.Collections;

public class App
{
	private static App app = new App();

	public static App Game { get { return app; } }

	private UCharacterMgr characterMgr = new UCharacterMgr ();
	public UCharacterMgr CharacterMgr { get { return characterMgr; } }

	public void Update ()
	{
		characterMgr.Update ();
	}
}

public class Main : MonoBehaviour {

	private readonly string[] index = new string[]{ "004", "006", "008" };
    /// <summary>
    /// 配置默认设备信息
    /// </summary>
	private const int DEFAULT_WEAPON = 0;
	private const int DEFAULT_HEAD = 2;
	private const int DEFAULT_CHEST = 0;
	private const int DEFAULT_HAND = 0;
	private const int DEFAULT_FEET = 1;
	private const bool DEFAULT_COMBINEMATERIAL = true;

    /// <summary>
    /// 用于GUI显示
    /// </summary>
    private bool combine = DEFAULT_COMBINEMATERIAL;
	private bool[] weapon_list = new bool[3];
	private bool[] head_list = new bool[3];
	private bool[] chest_list = new bool[3];
	private bool[] hand_list = new bool[3];
	private bool[] feet_list = new bool[3];

    /// <summary>
    /// 场景中的化身
    /// </summary>
    private UCharacterController character = null;

	// Use this for initialization
	void Start () {

        // UI显示
		weapon_list [DEFAULT_WEAPON] = true;
		head_list [DEFAULT_HEAD] = true;
		chest_list [DEFAULT_CHEST] = true;
		hand_list [DEFAULT_HAND] = true;
		feet_list [DEFAULT_FEET] = true;

        // 创建骨骼
		character = App.Game.CharacterMgr.Generatecharacter (
			"ch_pc_hou", 
			"ch_we_one_hou_" + index[DEFAULT_WEAPON],
			"ch_pc_hou_" + index[DEFAULT_HEAD] + "_tou", 
			"ch_pc_hou_" + index[DEFAULT_CHEST] + "_shen", 
			"ch_pc_hou_" + index[DEFAULT_HAND] + "_shou", 
			"ch_pc_hou_" + index[DEFAULT_FEET] + "_jiao",
			combine);
		character.Instance.transform.position = new Vector3 (0, -1, -5);
		character.Instance.transform.eulerAngles = new Vector3 (0, 180, 0);
	}
	
	// Update is called once per frame
	void Update () {
	
		App.Game.Update();
	}

	void OnGUI () {

		GUI.Button (new Rect (0, 0, 100, 30),   "装备 1");
		GUI.Button (new Rect (100, 0, 100, 30), "装备 2");
		GUI.Button (new Rect (200, 0, 100, 30), "装备 3");

		for (int i = 0; i < weapon_list.Length; i++) {
			
			if (GUI.Button (new Rect (i * 100, 30, 100, 50), "武器" + (weapon_list[i] ? "(√)" : ""))) {
				
				if (!weapon_list [i]) {
					for (int j = 0; j < weapon_list.Length; j++) {
						weapon_list [j] = false;
					}
					weapon_list [i] = true;
					
					character.ChangeWeapon ("ch_we_one_hou_" + index[i]);
				}
			}
		}

		for (int i = 0; i < head_list.Length; i++) {

			if (GUI.Button (new Rect (i * 100, 80, 100, 50), "头" + (head_list[i] ? "(√)" : ""))) {

				if (!head_list [i]) {
					for (int j = 0; j < head_list.Length; j++) {
						head_list [j] = false;
					}
					head_list [i] = true;

					character.ChangeHeadEquipment ("ch_pc_hou_" + index[i] + "_tou", combine);
				}
			}
		}

		for (int i = 0; i < chest_list.Length; i++) {

			if (GUI.Button (new Rect (i * 100, 130, 100, 50), "胸部" + (chest_list[i] ? "(√)" : ""))) {

				if (!chest_list [i]) {
					for (int j = 0; j < chest_list.Length; j++) {
						chest_list [j] = false;
					}
					chest_list [i] = true;

					character.ChangeChestEquipment ("ch_pc_hou_" + index[i] + "_shen", combine);
				}
			}
		}

		for (int i = 0; i < hand_list.Length; i++) {

			if (GUI.Button (new Rect (i * 100, 180, 100, 50), "手" + (hand_list[i] ? "(√)" : ""))) {

				if (!hand_list [i]) {
					for (int j = 0; j < hand_list.Length; j++) {
						hand_list [j] = false;
					}
					hand_list [i] = true;

					character.ChangeHandEquipment("ch_pc_hou_" + index[i] + "_shou", combine);
				}
			}
		}

		for (int i = 0; i < feet_list.Length; i++) {

			if (GUI.Button (new Rect (i * 100, 230, 100, 50), "脚" + (feet_list[i] ? "(√)" : ""))) {

				if (!feet_list [i]) {
					for (int j = 0; j < feet_list.Length; j++) {
						feet_list [j] = false;
					}
					feet_list [i] = true;

					character.ChangeFeetEquipment("ch_pc_hou_" + index[i] + "_jiao", combine);
				}
			}
		}

		if (GUI.Button(new Rect(Screen.width - 100,0,100,50),character.animationState == 0 ? "攻击" : "战立"))
		{
			if (character.animationState == 0)
			{
				character.PlayAttack();
			}else
			{
				character.PlayStand();
			}
		}

		if (GUI.Button(new Rect(Screen.width - 100,50,100,50),character.rotate ? "静止" : "旋转"))
		{
			if (character.rotate)
			{
				character.rotate = false;
			}else
			{
				character.rotate = true;
			}
		}

        if (GUI.Button(new Rect(Screen.width - 150, 100, 150, 50), combine ? "合并材质(√)" : "合并材质"))
        {
            combine = !combine;
        }
    }

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

public class UCharacterMgr  {

	private UCombineSkinnedMgr skinnedMgr = null;
	public UCombineSkinnedMgr CombineSkinnedMgr { get{ return skinnedMgr; } }

	private int characterIndex = 0;
	private Dictionary<int,UCharacterController> characterDic = new Dictionary<int, UCharacterController>();

	public UCharacterMgr () {

		skinnedMgr = new UCombineSkinnedMgr ();
	}

	public UCharacterController Generatecharacter (string skeleton, string weapon, string head, string chest, string hand, string feet, bool combine = false)
	{

		UCharacterController instance = new UCharacterController (characterIndex,skeleton,weapon,head,chest,hand,feet,combine);
		characterDic.Add(characterIndex,instance);
		characterIndex ++;

		return instance;
	}

	public void Removecharacter (CharacterController character)
	{

	}

	public void Update () {

		foreach(UCharacterController character in characterDic.Values)
		{
			character.Update();
		}
	}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class UCombineSkinnedMgr {

    /// <summary>
    /// 仅用于合并材料
    /// </summary>
	private const int COMBINE_TEXTURE_MAX = 512;
	private const string COMBINE_DIFFUSE_TEXTURE = "_MainTex";

    /// <summary>
    /// 将 SkinnedMeshRenderers 合并在一起共享一个骨架
    /// 合并材料将减少渲染管道,但是会增加内存空间
    /// </summary>
    /// <param name="skeleton">把网格与这个骨架结合起来(a gameobject)</param>
    /// <param name="meshes">需要合并网格</param>
    /// <param name="combine">是否合并材料</param>
	public void CombineObject (GameObject skeleton, SkinnedMeshRenderer[] meshes, bool combine = false){

        // 取出骨骼的全部骨骼
        List<Transform> transforms = new List<Transform>();
		transforms.AddRange(skeleton.GetComponentsInChildren<Transform>(true));

		List<Material> materials = new List<Material>();//the list of materials
		List<CombineInstance> combineInstances = new List<CombineInstance>();//the list of meshes
		List<Transform> bones = new List<Transform>();//the list of bones

        // 以下信息仅用于合并材料(bool combine = true)
        List<Vector2[]> oldUV = null;
		Material newMaterial = null;
		Texture2D newDiffuseTex = null;

        //收集信息网格
        for (int i = 0; i < meshes.Length; i ++)
		{
			SkinnedMeshRenderer smr = meshes[i];
			materials.AddRange(smr.materials); // Collect materials
			//  选择网格
			for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++)
			{
				CombineInstance ci = new CombineInstance();
				ci.mesh = smr.sharedMesh;
				ci.subMeshIndex = sub;
				combineInstances.Add(ci);
			}
			// 选择骨骼
			for (int j = 0 ; j < smr.bones.Length; j ++)
			{
				int tBase = 0;
				for (tBase = 0; tBase < transforms.Count; tBase ++)
				{
					if (smr.bones[j].name.Equals(transforms[tBase].name))
					{
						bones.Add(transforms[tBase]);
						break;
					}
				}
			}
		}

        // 合并材质
		if (combine)
		{
			newMaterial = new Material (Shader.Find ("Mobile/Diffuse"));
			oldUV = new List<Vector2[]>();
			// 合并图片
			List<Texture2D> Textures = new List<Texture2D>();
			for (int i = 0; i < materials.Count; i++)
			{
				Textures.Add(materials[i].GetTexture(COMBINE_DIFFUSE_TEXTURE) as Texture2D);
			}

			newDiffuseTex = new Texture2D(COMBINE_TEXTURE_MAX, COMBINE_TEXTURE_MAX, TextureFormat.RGBA32, true);
			Rect[] uvs = newDiffuseTex.PackTextures(Textures.ToArray(), 0);
			newMaterial.mainTexture = newDiffuseTex;

            // 重置紫外线
            Vector2[] uva, uvb;
			for (int j = 0; j < combineInstances.Count; j++)
			{
				uva = (Vector2[])(combineInstances[j].mesh.uv);
				uvb = new Vector2[uva.Length];
				for (int k = 0; k < uva.Length; k++)
				{
					uvb[k] = new Vector2((uva[k].x * uvs[j].width) + uvs[j].x, (uva[k].y * uvs[j].height) + uvs[j].y);
				}
				oldUV.Add(combineInstances[j].mesh.uv);
				combineInstances[j].mesh.uv = uvb;
			}
		}

		//创建新的SkinnedMeshRenderer
		SkinnedMeshRenderer oldSKinned = skeleton.GetComponent<SkinnedMeshRenderer> ();
		if (oldSKinned != null) {

			GameObject.DestroyImmediate (oldSKinned);
		}
		SkinnedMeshRenderer r = skeleton.AddComponent<SkinnedMeshRenderer>();
		r.sharedMesh = new Mesh();
		r.sharedMesh.CombineMeshes(combineInstances.ToArray(), combine, false);// 组合网格
        r.bones = bones.ToArray();//使用新骨骼
		if (combine)
		{
			r.material = newMaterial;
			for (int i = 0 ; i < combineInstances.Count ; i ++)
			{
				combineInstances[i].mesh.uv = oldUV[i];
			}
		}else
		{
			r.materials = materials.ToArray();
		}
	}
}

运行效果图:

资源下载地址(带全部资源):

链接:https://pan.baidu.com/s/1MUFtEwp8ZVSUHxoeB99h3g 
提取码:zc34 
 

猜你喜欢

转载自blog.csdn.net/QWBin/article/details/84170472
今日推荐