今天讲一下如何换武器 首先我们要知道在unity 中所有东西都是网格绘制的 ,在计算机图形学中
我们看到计算机中的一切东西都是无数个三角形绘制出来的,这个时候我们就会有疑问为什吗要说网格绘制?换武器的是在骨骼上面呈现 ,我们在骨骼上面进行换装 换衣服 换头 所以我们换武器也可以归类其中
创建一个骨骼空对象我们要往上面加mesh进行绘制 人物
首先认识
带蒙皮的网格渲染器 (Skinned Mesh Renderer)
Unity 使用__带蒙皮的网格渲染器 (Skinned Mesh Renderer)__ 组件来渲染__骨骼__动画;此类动画中的网格形状由预定义的动画序列进行变形。这种技术对于关节弯曲的角色和其他对象(与关节更像铰链的机器相反)非常有用。
带蒙皮的网格渲染器会在导入时自动添加到需要它的网格。
我们在脚本里面加这行代码进行动态添加
SkinnedMeshRenderer skinned;//带蒙皮的网格渲染器 (Skinned Mesh Renderer)
GameObject[] bodys;//人物身体
GameObject[] weapons; //武器
void Start()
{
skinned= gameObject.AddComponent<SkinnedMeshRenderer>();
}
我们要首先考虑身上的网格
1网格合并
//手动创建网格
Mesh mesh = new Mesh();
List<CombineInstance> combines = new List<CombineInstance>();//组合的网格
for (int i = 0; i < bodys.Length; i++)
{
CombineInstance combine = new CombineInstance();
combine.mesh = bodys[i].GetComponent<SkinnedMeshRenderer>().sharedMesh;//获得网格
//添加到组合的网格
combines.Add(combine);
}
//合并--将多个网格合并到此网格中。
mesh.CombineMeshes(combines.ToArray(), false, false);
//如果 mergeSubMeshes 为 true,则所有网格都会合并到单个子网格中。否则,每个网格会放置在不同的子网格中。如果所有网格都共享相同的材质,则此属性应设置为 true。
//如果 useMatrices 为 true,则使用 CombineInstance 结构中的变换矩阵。否则,忽略它们。
2材质 与纹理合并
//合并材质
List<Material> materials = new List<Material>();
for (int i = 0; i < bodys.Length; i++)
{
materials.Add(bodys[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial); //获得材质
}
skinned.materials = materials.ToArray();
3骨骼的使用
//骨骼
//找到自身骨骼
Transform[] mybones = GetComponentsInChildren<Transform>();
//存入字典
Dictionary<string, Transform> dic = new Dictionary<string, Transform>();
foreach (var item in mybones)
{
dic.Add(item.name, item);
}
//创建需要合并的集合
List<Transform> bones = new List<Transform>();
//查看所有的子节点
for (int i = 0; i < bodys.Length; i++)
{
Transform[] bodybone = bodys[i].GetComponentInChildren<SkinnedMeshRenderer>().bones;
foreach (var item in bodybone)
{
if (dic.ContainsKey(item.name))
{
bones.Add(item);
}
}
}
skinned.bones = bones.ToArray();//骨骼赋值
现在我们已经可以生成人物了
我们可以尝试更换衣服
我们现在需要拿到手的节点去进行实例化武器
在这个节点创造空对象
我们可以试试托进入一个武器
因为策划给的资源有可能是放大的所以我们要修改mesh
nice
已经是正常大小我们只需要调整一下欧拉角就行了
注意点 :要调整的是hand这个武器父级的角度
我们之后就可以通过代码删除当前的手的子物体
添加公开属性
public void ChangWeapon()
{
weaponsIndex++;
if (weaponsIndex>=weapons.Length)
{
weaponsIndex = 0;
}
if (hand.childCount>0)
{
Destroy(hand.GetChild(0).gameObject);
}
var obj=Instantiate(weapons[weaponsIndex],hand);
obj.transform.position = hand.position;
}
控制器
using System.Collections.Generic;
using UnityEngine;
public class Hero : MonoBehaviour
{
SkinnedMeshRenderer skinned;//带蒙皮的网格渲染器 (Skinned Mesh Renderer)
public GameObject[] bodys;//人物身体
public GameObject[] weapons; //武器
public int weaponsIndex=-1;
public Transform hand;
void Start()
{
skinned = gameObject.AddComponent<SkinnedMeshRenderer>();
//手动创建网格
Mesh mesh = new Mesh();
List<CombineInstance> combines = new List<CombineInstance>();//组合的网格
for (int i = 0; i < bodys.Length; i++)
{
CombineInstance combine = new CombineInstance();
combine.mesh = bodys[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh;//获得网格
//添加到组合的网格
combines.Add(combine);
}
//合并--将多个网格合并到此网格中。
mesh.CombineMeshes(combines.ToArray(), false, false);
skinned.sharedMesh = mesh;
//如果 mergeSubMeshes 为 true,则所有网格都会合并到单个子网格中。否则,每个网格会放置在不同的子网格中。如果所有网格都共享相同的材质,则此属性应设置为 true。
//如果 useMatrices 为 true,则使用 CombineInstance 结构中的变换矩阵。否则,忽略它们。
//合并材质
List<Material> materials = new List<Material>();
for (int i = 0; i < bodys.Length; i++)
{
materials.Add(bodys[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial); //获得材质
}
skinned.materials = materials.ToArray();
//骨骼
//找到自身骨骼
Transform[] mybones = GetComponentsInChildren<Transform>();
//存入字典
Dictionary<string, Transform> dic = new Dictionary<string, Transform>();
foreach (var item in mybones)
{
dic.Add(item.name, item);
}
//创建需要合并的集合
List<Transform> bones = new List<Transform>();
//查看所有的子节点
for (int i = 0; i < bodys.Length; i++)
{
Transform[] bodybone = bodys[i].GetComponentInChildren<SkinnedMeshRenderer>().bones;
foreach (var item in bodybone)
{
if (dic.ContainsKey(item.name))
{
bones.Add(item);
}
}
}
skinned.bones = bones.ToArray();//骨骼赋值
ChangWeapon();
}
public void ChangWeapon()
{
weaponsIndex++;
if (weaponsIndex>=weapons.Length)
{
weaponsIndex = 0;
}
if (hand.childCount>0)
{
Destroy(hand.GetChild(0).gameObject);
}
var obj=Instantiate(weapons[weaponsIndex],hand);
obj.transform.position = hand.position;
}
// Update is called once per frame
void Update()
{
}
}
效果