写这个文章的目的就是为了初学unity,然后更好的掌握unity中的内容【主要是代码】
学习unity的途径是Brackeys 的教程;
接上篇: unity learning RPG Leaning(五).
1、需要将物体装备到player身上;
2、对于palyer以及物体的模型重新导入和优化;
3、把Equipment改变格式调到界面上
1、创立一个Equipment类继承Item类:public class Equipment : Item
2、创建Equipment里的分类:这里用了枚举法,把种类的类型直接抛出到公用;
public enum EquipmentSlot { Head, Chest, Legs, Weapon, feet, Shield }【在Equipment类外】
3、在Equipment类中定义EquipmentSlot 【种类】、armorModifier和damageModifier【这两个应该是损耗值和装备的武力值吧。这里不确定,只知道是和武器、血条有关的】
4、重写Item类的USE()函数
public override void USE() //重写
{
base.USE();
EquipmentManager.instance.Equip(this); //在GameManager中创建一个EquimentManager
removeFromInventory(); //在Item的定义函数
}
这里的removeFromInventory(); //在Item的定义函数
public void removeFromInventory()
{
Inventory.instance.RemoveItem(this);
}
在GameManager中创建一个EquimentManager类。总体的装备库,也需要用Awake()来申明全局instance。
设置一个currentEquipment的数组用来存放Equipment;然后用逻辑来写Equip和UnEquip的函数。
现在基本上就是可以做到了装备物体,卸下物体;然后用新的模型「加入了装备等东西」来优化整个游戏。
1、更新完模型之后,把模型的mesh导出来,由于模型是Skinned Mesh Render所以单独放置在场景中是不会有什么效果的。如果需要单独显示,后面会详细说明如何显示。
然后根据模型,创建相应的Equipment;
然后在Equipment改写:
加入
public SkinnedMeshRenderer mesh;【Equipment类】
然后在界面中加入对应的网格
其中,hair之类的,我们设定为默认的Item,使之一开始就出现在页面上
这里主要是把我们的Equipment的网格显示出来
SkinnedMeshRenderer[] currentMesh;
Equip():加入网格
SkinnedMeshRenderer newMesh = Instantiate<SkinnedMeshRenderer>(newItem.mesh);
newMesh.transform.parent = targetMesh.transform;
newMesh.bones = targetMesh.bones;
newMesh.rootBone = targetMesh.rootBone;
currentMesh[indexSlot] = newMesh;
public Equipment[] defaultEquipment;
void SetEquipDefault() //调用这个函数即可
{
foreach (Equipment equit in defaultEquipment)
{
Equip(equit);
}
}
穿衣服的时候可能回穿模,所以调节BlendShapes的大小来控制;
由于每一个装备对应不同的部位,所以在【Equipment类】中加入
public EquipmentMeshRegion[] coveredMeshRegions;
申明新的枚举类
public enum EquipmentMeshRegion {
Legs, Arms, Torso }
在【EquimentManage类】中来实现变化大小
void SetEquipmentMeshRegion(Equipment item, int weight)
{
foreach (EquipmentMeshRegion blendShape in item.coveredMeshRegions)
{
targetMesh.SetBlendShapeWeight((int)blendShape, weight);
}
}
在对应部分调用即可
上文说到了,Skinned Mesh Render所以单独放置在场景中是不会有什么效果的。如果需要单独显示,需要把这个Skinned Mesh Render 变成Mesh Render。
我们就把刚刚的网格拖到界面中,发现没有显示任何的物体。
我们就写一个类,来把Skinned Mesh Render变成Mesh Render。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ConvertMesh : MonoBehaviour
{
[ContextMenu("Convert to regular mesh")]
void convert()
{
SkinnedMeshRenderer skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();
MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
meshRenderer.sharedMaterials = skinnedMeshRenderer.sharedMaterials;
meshFilter.sharedMesh = skinnedMeshRenderer.sharedMesh;
DestroyImmediate(skinnedMeshRenderer);
DestroyImmediate(this)
}
}
[ContextMenu(“Convert to regular mesh”)]的作用就是把这个函数放到我们的界面中,方便调用
点击之后,会在这个模型中直接调用这个方法,会直接把Skinned Mesh Render变成Mesh Render。
就可以在屏幕中显示了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Equipment", menuName = "Inventory/Euqipment")]
public class Equipment : Item
{
public EquipmentSlot equipsolt;
public SkinnedMeshRenderer mesh;
public EquipmentMeshRegion[] coveredMeshRegions;
public int armorModifier;
public int damageModifier;
public override void USE()
{
base.USE();
EquipmentManager.instance.Equip(this);
removeFromInventory();
}
}
public enum EquipmentSlot {
Head, Chest, Legs, Weapon, feet, Shield }
public enum EquipmentMeshRegion {
Legs, Arms, Torso }
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EquipmentManager : MonoBehaviour
{
#region Singlete
public delegate void OnEquipmentChanged(Equipment newItem, Equipment oldItem);
public OnEquipmentChanged onEquipmentChanged;
public SkinnedMeshRenderer targetMesh;
public static EquipmentManager instance;
public Equipment[] defaultEquipment;
Inventory inventory;
void Awake()
{
if (instance != null)
{
Debug.Log("More than one instance of inventory found!");
return;
}
instance = this;
}
#endregion
Equipment[] currentEquipment;
SkinnedMeshRenderer[] currentMesh;
void Start()
{
int numSlot = System.Enum.GetNames(typeof(EquipmentSlot)).Length;
currentEquipment = new Equipment[numSlot];
currentMesh = new SkinnedMeshRenderer[numSlot];
inventory = Inventory.instance;
SetEquipDefault();
}
public void Equip(Equipment newItem)
{
Equipment oldItem = null;
int indexSlot = (int)newItem.equipsolt;
// if (currentEquipment[indexSlot] != null)
// {
// oldItem = currentEquipment[indexSlot];
// inventory.AddItem(oldItem);
// }
oldItem = UnEquip(indexSlot);
currentEquipment[indexSlot] = newItem;
SkinnedMeshRenderer newMesh = Instantiate<SkinnedMeshRenderer>(newItem.mesh);
newMesh.transform.parent = targetMesh.transform;
newMesh.bones = targetMesh.bones;
newMesh.rootBone = targetMesh.rootBone;
currentMesh[indexSlot] = newMesh;
SetEquipmentMeshRegion(newItem, 100);
if (onEquipmentChanged != null)
{
onEquipmentChanged(newItem, oldItem);
}
}
public Equipment UnEquip(int indexSold)
{
if (currentEquipment[indexSold] != null)
{
if (currentMesh[indexSold] != null)
{
Destroy(currentMesh[indexSold].gameObject);
}
Equipment oldItem = currentEquipment[indexSold];
inventory.AddItem(oldItem);
currentEquipment[indexSold] = null;
SetEquipmentMeshRegion(oldItem, 0);
if (onEquipmentChanged != null)
{
onEquipmentChanged(null, oldItem);
}
return oldItem;
}
return null;
}
public void UnEquipAll()
{
for (int i = 0; i < currentEquipment.Length; i++)
{
UnEquip(i);
}
SetEquipDefault();
}
void SetEquipmentMeshRegion(Equipment item, int weight)
{
foreach (EquipmentMeshRegion blendShape in item.coveredMeshRegions)
{
targetMesh.SetBlendShapeWeight((int)blendShape, weight);
}
}
void SetEquipDefault()
{
foreach (Equipment equit in defaultEquipment)
{
Equip(equit);
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.U))
{
UnEquipAll();
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ConvertMesh : MonoBehaviour
{
[ContextMenu("Convert to regular mesh")]
void convert()
{
SkinnedMeshRenderer skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();
MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
meshRenderer.sharedMaterials = skinnedMeshRenderer.sharedMaterials;
meshFilter.sharedMesh = skinnedMeshRenderer.sharedMesh;
DestroyImmediate(skinnedMeshRenderer);
DestroyImmediate(this);
}
}