添加一把 bank 的完整流程:
1. 创建Attribute
创建一个空类vp_InventoryItemsAttribute : PropertyAttribute,继承自PropertyAttribute代表实现一个叫vp_InventoryItems的Attribute(编译器扩展的一个属性)
所以现在我们能够在一个脚本中通过 [ InventoryItems ] 来调用我们自己实现的编译器扩展属性,但是这个Attribute目前没有实现任何绘制逻辑,因为我们没实现它的PropertyDrawer对象
2. 实现Drawer
实现vp_InventoryItems(Attribute)的PropertyDrawer,实现绘制的逻辑
[CustomPropertyDrawer(typeof(vp_InventoryItemsAttribute))]
public class vp_InventoryItemsDrawer : PropertyDrawer
在这个类中我们就要实现绘制的逻辑了,因为我们目的是绘制背包inventory的面板,所以我们通过
OnGUI(Rect pos, SerializedProperty prop, GUIContent label)
这个prop属性是我们调用这个编译器扩展Attribute的属性。
比如:在vp_Inventory类中
[vp_InventoryItems]
public float itemList; 那么在这里我们的prop就是这个itemList对象,所以我们能通过
vp_Inventoryinventory=((vp_Inventory)prop.serializedObkect.targetObject)
通过这个属性对象来找到他的脚本物体,也就是inventory对象。
3. 实现OnGUI
在这里我们实现
(1).绘制所有内部的bank实例
1. bank实例中封装的bank对象的名称(对应的asset文件名,并加上''internal '')
2.这个bank对象的图标(存在于item对象中)
3.绘制这个bank实例的unit数量(内部bank的id无意义)
4.绘制一个×,用于移除这个bank实例
(2).绘制背包中的所有外部bank实例集合
1. bank实例中封装的bank对象的名称(对应的asset文件名)
2.这个bank对象的图标(存在于item对象中)
3.绘制这个bank实例的unit数量及它的id的值
4.绘制一个×,用于移除这个bank实例
(3).绘制背包中所有item实例集合
1. item实例中封装的item对象的名称(对应的asset文件名)
2.这个item对象的图标
3.绘制这个item实例的id的值
4.绘制一个×,用于移除这个bank实例
(4).绘制一个框,用于拖拽添加新的item对象进背包
1. 调用inventory.TryGiveItem方法
(5). 创建一个item对象,用asset文件保存
现在我们知道item对象是联系背包的基础,item对象是item类的实例化,我们可以通过MFPS菜单来直接创建一个item对象,这个item对象以asset文件的形式存在,直接生成在我们unity文件下,我们来看看其中的流程
1. UFPSMenu类:设置菜单,类中有这么一个方法
[MenuItem("UFPS/Wizards/Create Item Type/Item", false, 101)]
public static void CreateItemTypeVpItemType()
{
vp_ItemType asset =
(vp_ItemType)vp_EditorUtility.CreateAsset("UFPS/Base/Content/ItemTypes" ,typeof(
vp_ItemType) );
}
2. CreateAsset方法:(最主要的2行)
//创建一个item对象
Object asset = ScriptableObject.CreateInstance(type);
//将 item 对象序列化,并用一个Asset文件保存
AssetDatabase.CreateAsset(asset, "Assets/" + fileName + ".asset");
3. 再来看Item类:
[System.Serializable]
vp_ItemType : ScriptableObject
首先,你要保存item对象,那肯定要序列化吧,能序列化才能把一个对象变成一串二进制流数据,然后,你想将这串二进制数据保存到asset文件中,所以item类必须继承
ScriptableObject类,unity才能把序列化后的数据写入到asset文件中
4. 修改item对象的字段值
我们现在在文件夹下有一个以asset文件存在的item对象,既然这是一个对象,那么我们就能够对他的字段的值进行赋值与更改,(就好比你把一个脚本类拖拽到游戏物体上,这个脚本就变成了对象,你就可以在编辑器上对脚本中的各字段进行更改与赋值),同理的,我们也能在右边编辑器面板上对这个asset文件进行编辑,自己修改其中各字段的值(具体的实现通过item的编辑器扩展)
(6). 将这个item对象(asset文件)添加到背包
1. 将asset文件拖拽到我们的inventory的添加框中,unity会自动识别这个asset文件成一个item对象(解析?)并作为参数传入,然后背包调用inventory.TryGiveItem方法,将这个item对象封装成一个item实例(就多了一个id,id默认为0,表示不使用),然后将这个item实例添加进背包的ItemInstances集合中
2. 容量限制:
实现一个vp_InventoryCapsAttribute和vp_InventoryCapsDrawer
1.绘制一个框,连接cap功能是否启用
2.绘制背包内所有的ItemCap对象(在item对象上加一个cap)
1.item对象名+ item类型(item,bank,unit)
2.点击自动找到引用的item对象(asset文件)
3.绘制一个cap字段和输入框,更改ItemCap的容量cap
3.绘制一个拖拽框
当我们将一个item对象(asset文件),拖拽到它上面,调用 inventory.SetItemCap,(如果没有ItemCap)创建一个新的ItemCap对象,这个ItemCap对象的item对象引用直接指向我们的asset文件(item对象),然后设置默认的cap,我们直接通过面板属性调整cap的值即可(PS:如果我们再次拖拽这个item,因为我们背包中已经有这个item对象的itemCap了,只需要调整后面的cap值即可,所以弹出一个提示框)
3. 背包空间限制:
原理同上,这个就比较简单了,每个item对象都有space属性(默认为0),我们绘制一个space的输入框,修改背包的空间,然后绘制一个进度条,表示背包空间的使用量
4. 再次添加:
当我们再次将我们的asset文件(item对象)拖拽到添加框中,我们先检查空间space是否足够,然后进行cap的检查,找到我们的itemCap对象,获取容量限制,然后获取我们背包中这个item的数量,比较,最后添加
(3)比方:
1. 生成榴弹枪类:(bank对象)
我们手上的asset文件(bank对象)代表:榴弹枪,我们设置榴弹枪的容量,10发,设置榴弹枪的子弹:火焰弹(也是一个unit对象),这种枪允许重装子弹,不会子弹没了就消失,ok,配置完榴弹枪了
2. 生成一把榴弹枪实体:(bankInstance)
我们通过拖拽,在背包中生成了一把榴弹枪实体,默认的子弹数量设置为枪的最大容量:TryGiveUnitBank(unitBankType, unitBankType.Capacity, id),ok现在我们就成功向背包添加了一把榴弹枪了,这把枪当前的子弹为10(最大容量)