[unity learning] RPG Leaning(六)

[unity learning] RPG Leaning(六)

写这个文章的目的就是为了初学unity,然后更好的掌握unity中的内容【主要是代码】
学习unity的途径是Brackeys 的教程;
接上篇: unity learning RPG Leaning(五).

目的

1、需要将物体装备到player身上;
2、对于palyer以及物体的模型重新导入和优化;
3、把Equipment改变格式调到界面上

一、将物体装备到player身上

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);
  }
EquimentManager类

在GameManager中创建一个EquimentManager类。总体的装备库,也需要用Awake()来申明全局instance。

设置一个currentEquipment的数组用来存放Equipment;然后用逻辑来写Equip和UnEquip的函数。

二、对于palyer以及物体的模型重新导入和优化

现在基本上就是可以做到了装备物体,卸下物体;然后用新的模型「加入了装备等东西」来优化整个游戏。
[unity learning] RPG Leaning(六)_第1张图片

[unity learning] RPG Leaning(六)_第2张图片
[unity learning] RPG Leaning(六)_第3张图片

模型的更新

1、更新完模型之后,把模型的mesh导出来,由于模型是Skinned Mesh Render所以单独放置在场景中是不会有什么效果的。如果需要单独显示,后面会详细说明如何显示。
[unity learning] RPG Leaning(六)_第4张图片

[unity learning] RPG Leaning(六)_第5张图片

然后根据模型,创建相应的Equipment;
[unity learning] RPG Leaning(六)_第6张图片
然后在Equipment改写:
加入

  public SkinnedMeshRenderer mesh;【Equipment类】

然后在界面中加入对应的网格
[unity learning] RPG Leaning(六)_第7张图片
其中,hair之类的,我们设定为默认的Item,使之一开始就出现在页面上
[unity learning] RPG Leaning(六)_第8张图片

EquimentManage类改写

这里主要是把我们的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;
加入默认的衣服【EquimentManage类】
  public Equipment[] defaultEquipment;

  void SetEquipDefault() //调用这个函数即可
  {
     
    foreach (Equipment equit in defaultEquipment)
    {
     
      Equip(equit);
    }
  }
blenderShapes的控制

穿衣服的时候可能回穿模,所以调节BlendShapes的大小来控制;
[unity learning] RPG Leaning(六)_第9张图片
[unity learning] RPG Leaning(六)_第10张图片
由于每一个装备对应不同的部位,所以在【Equipment类】中加入

  public EquipmentMeshRegion[] coveredMeshRegions;

申明新的枚举类

public enum EquipmentMeshRegion {
      Legs, Arms, Torso }

然后在每一个Equipment中加入对应要缩放的部位
[unity learning] RPG Leaning(六)_第11张图片

在【EquimentManage类】中来实现变化大小

 void SetEquipmentMeshRegion(Equipment item, int weight)
  {
     
    foreach (EquipmentMeshRegion blendShape in item.coveredMeshRegions)
    {
     
      targetMesh.SetBlendShapeWeight((int)blendShape, weight);
    }
  }

在对应部分调用即可

三、把Equipment改变格式调到界面上

[unity learning] RPG Leaning(六)_第12张图片

上文说到了,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”)]的作用就是把这个函数放到我们的界面中,方便调用
[unity learning] RPG Leaning(六)_第13张图片
[unity learning] RPG Leaning(六)_第14张图片

点击之后,会在这个模型中直接调用这个方法,会直接把Skinned Mesh Render变成Mesh Render。
就可以在屏幕中显示了。

代码

Equipment
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 }

EquipmentManager

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();
    }
  }
}

ConvertMesh

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);

  }
}

你可能感兴趣的:(unity,RPG,Game,unity)