Unity Avatar换装原理实例

本文向大家介绍Unity换装原理及其简单实现

首先附上效果图:


本文的源码我将上传提供大家下载点击打开链接

实现原理:控制角色SkinMeshRenderer组件的mesh、materials、bones属性来实现角色换装

在该Demo素材中,主角是由多个网格拼接完成

其中网格对象上添加了SkinMeshRenderer组件,并指定了material、mesh、root bone

我们不采用这种方式来渲染角色

我们把角色的全部materials、mesh、bones绑定到一个SkinMeshRenderer上,其中这种做法需要注意的是materials和bones需要一一对应起来,否则渲染紊乱

好的,接下来我将写一个实例实现换装(下载参考源码方便理解)

我们Ctrl+D复制Female对象除了Female_Hips子节点保留(骨骼节点),其他都Delete

在Female节点上添加SkinMeshRenderer组件

首先随机获取到子网格

GameObject go = list[Random.Range(0, list.Count)];

			SkinnedMeshRenderer goSMR = go.GetComponent<SkinnedMeshRenderer>();
			if (goSMR)
			{
				CombineInstance ci = new CombineInstance();
				ci.mesh = goSMR.sharedMesh;
				ciList.Add(ci);
				materialList.AddRange(goSMR.materials);
				//遍历角色所有的骨骼节点来找到相对应得骨骼
				GetBone(goSMR.bones);
			}



其中遍历节点方式是通过节点名字来获取,将获得骨骼节点,通过遍历获得

foreach (Transform x in t)
		{
			foreach (Transform y in allBones)
			{
				if (y.name.Equals(x.name))
				{
					boneList.Add(y);
					break;
				}
			}
		}


最后生成角色蒙皮

mesh = new Mesh();
		mesh.CombineMeshes(ciList.ToArray(),false,false);
		smr.sharedMesh = mesh;

		smr.materials = materialList.ToArray();

		smr.bones = boneList.ToArray();


最终脚本

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

[RequireComponent(typeof(SkinnedMeshRenderer))]
public class GeneraterAvatar : MonoBehaviour
{
	private enum GeneraterType
	{
		ALL,
		EYE,
		FACE,
		HAIR,
		PANT,
		SHOES,
		BODY
	}

	//可以供选择的对象列表
	public List<GameObject> eyeList = new List<GameObject>();
	public List<GameObject> faceList = new List<GameObject>();
	public List<GameObject> hairList = new List<GameObject>();
	public List<GameObject> pantList = new List<GameObject>();
	public List<GameObject> shoesList = new List<GameObject>();
	public List<GameObject> bodyList = new List<GameObject>();

	//角色的SkinMeshRenderer组件上的材质列表
	private List<Material> materialList = new List<Material>();
	//角色的SkinMeshRenderer组件上的骨骼列表
	private List<Transform> boneList = new List<Transform>();
	//角色的子网格,对这些子网格进行拼接后形成角色的完整网格
	private List<CombineInstance> ciList = new List<CombineInstance>();
	//角色的网格
	private Mesh mesh;
	//角色的骨骼节点
	private Transform[] allBones;
	//组件
	private SkinnedMeshRenderer smr;
	// Use this for initialization
	void Start ()
	{
		//获取蒙皮组件
		smr = this.GetComponent<SkinnedMeshRenderer>();
		//随机种子
		Random.seed = (int)Time.time;
		//获取各个骨骼节点
		allBones = this.GetComponentsInChildren<Transform>();

		//生成
		GeneraterSkin(GeneraterType.ALL);
	}
	
	// Update is called once per frame
	void Update ()
	{
		if (Input.GetKeyDown(KeyCode.Space))
		{
			GeneraterSkin(GeneraterType.ALL);
		}

	}

	private void Reset()
	{
		ciList.Clear();
		materialList.Clear();
		boneList.Clear();
	}

	/// <summary>
	/// 生成蒙皮
	/// </summary>
	private void GeneraterSkin(GeneraterType type)
	{
		Reset();

		GetNextSkin(eyeList);
		GetNextSkin(faceList);
		GetNextSkin(hairList);
		GetNextSkin(pantList);
		GetNextSkin(shoesList);
		GetNextSkin(bodyList);

		mesh = new Mesh();
		mesh.CombineMeshes(ciList.ToArray(),false,false);
		smr.sharedMesh = mesh;

		smr.materials = materialList.ToArray();

		smr.bones = boneList.ToArray();
	}

	/// <summary>
	/// 随机获得蒙皮
	/// </summary>
	private void GetNextSkin(List<GameObject> list)
	{
		if (list.Count > 0)
		{
			GameObject go = list[Random.Range(0, list.Count)];

			SkinnedMeshRenderer goSMR = go.GetComponent<SkinnedMeshRenderer>();
			if (goSMR)
			{
				CombineInstance ci = new CombineInstance();
				ci.mesh = goSMR.sharedMesh;
				ciList.Add(ci);
				materialList.AddRange(goSMR.materials);
				//遍历角色所有的骨骼节点来找到相对应得骨骼
				GetBone(goSMR.bones);
			}
		}
	}

	/// <summary>
	/// 遍历角色所有的骨骼节点来找到相对应得骨骼
	/// </summary>
	/// <returns></returns>
	private void GetBone(Transform[] t)
	{
		foreach (Transform x in t)
		{
			foreach (Transform y in allBones)
			{
				if (y.name.Equals(x.name))
				{
					boneList.Add(y);
					break;
				}
			}
		}
	}
}

将其挂载到Female节点上


并为其制定相对应的对象(含SkinMeshRenderer组件)


在这个重点需要提出的是:

CombineInstance ci = new CombineInstance();
		ci.mesh = goSMR.sharedMesh;
		ciList.Add(ci);
		mesh = new Mesh();
		mesh.CombineMeshes(ciList.ToArray(),false,false);
		smr.sharedMesh = mesh;


该函数作用是将多个子网格进行拼接结合


本人也在寻找一份游戏开发实习工作,如果大佬们需要开发人员,请把我带走奋斗

这是我的简历:resume.liujunliang.com.cn/resume.pdf

作品的话可以私聊我哦!


==================== 即步 CSDN博客专栏=================

博客地址:http://blog.liujunliang.com.cn  

个人网站:http://www.liujunliang.com.cn     

==================== battle for programming =============


  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Unity Avatar 系统是一个用于创建和控制角色动画的工具。它的原理是通过将角色模型的骨架与动画控制器结合起来,使得角色能够根据不同的动作进行动画表现。 具体来说,Unity Avatar 系统的工作流程如下: 1. 创建角色模型:首先需要创建一个角色模型,包括角色的骨架和皮肤(即角色的外表)。 2. 创建动画控制器:为了让角色能够执行不同的动作,需要创建一个动画控制器。动画控制器是一个用于控制动画的状态机,通过将不同的动作状态连接起来,可以让角色根据不同的状态进行相应的动画表现。 3. 创建 Avatar:在创建角色模型时,需要将其绑定到一个 Avatar 上。Avatar 是一个用于描述角色骨架的数据结构,通过将角色模型的骨架与 Avatar 进行绑定,可以让角色模型在执行动画时正确地进行骨骼变。 4. 创建动画剪辑:动画剪辑是一段动画序列,用于描述角色在某个状态下的动画表现。通过将不同的动画剪辑与动画控制器相连,可以让角色在不同的状态下执行相应的动画。 5. 控制角色动画:最后,在游戏运行时,通过对动画控制器中的参数进行设置,可以控制角色执行不同的动画。例如,可以通过控制动画控制器中的“移动速度”参数来控制角色的行走动画。 综上所述,Unity Avatar 系统的原理主要是通过将角色模型、动画控制器和 Avatar 进行结合,使得角色能够根据不同的动作进行动画表现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值