版权声明:转载请注明出处。 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