以后都按照插件使用,提出问题,回答问题的方式来进行总结和学习

效果图

1、运行相关的例子,场景中出现4个矩形,这4个矩形是用来模拟物品掉落的包裹,移动Player靠近物品

2、使用鼠标点击物品正方体,点击I键打开包裹,这里看到3个掉落包裹正方体已经点没有了,相应的背包里多出三个苹果,至此例子演示完毕

插件使用

使用Inventory Pro进行装备的拾取,有很简单的例子

1、点击菜单Tool,InventorySystem,Main editor 打开自定义Editor

2、在Main manager对话框中点击Items editor选项卡,选中Item editor 点击Create Item 绿色按钮,会弹出左侧的选择子对话框,其中列出了可以创建的Item种类,第一项就是消耗品,当然还有很多别的东西,这里先试验最简单的消耗品

3、点击创建消耗品以后会出来一个Item的详情界面,这里需要添加Item的Name,Icon,Behavier里有类型,冷却时间,价格,是否可以叠放,是否可以丢弃等等属性吧,同时Editor会创建出相应的物品prefab,直接拖拽到场景中即可

问题

1、地上的包裹(Item容器)是如何产生的?

2、地上的包裹是如何对应Item model的,且之间的关系是什么?

3、拾取的过程是怎么样的?

答案

1、地上的包裹(Item容器)是如何产生的?

A1、这里例子里面是通过Unity3d Editor扩展进行添加地上的包裹的且是Cude,其中使用了动态生成预设的技术,这里涉及到很多关于Editor扩展的知识,基本与本章主题无关,Inventory Pro的作者也只是通过例子进行了展示(我想如果是实际游戏可能需要动态生成,比如生长点,怪物掉落什么的),这里列出一个动态生成Prefab的核心代码,也就是类似选择生成消耗品后点击的事件的处理函数,代码如下:

  1. protected override void CreateNewItem()
  2. {
  3. var picker = EditorWindow.GetWindow<InventoryItemTypePicker>(true);
  4. picker.Show(InventoryEditorUtil.selectedDatabase);
  5.  
  6. picker.OnPickObject += (type) =>
  7. {
  8. string prefabPath = EditorPrefs.GetString("InventorySystem_ItemPrefabPath") + "/item_" + System.DateTime.Now.ToFileTimeUtc() + "_PFB.prefab";
  9.  
  10. var obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
  11. var prefab = PrefabUtility.CreatePrefab(prefabPath, obj);
  12.  
  13. AssetDatabase.SetLabels(prefab, new string[] { "InventoryItemPrefab" });
  14.  
  15. var comp = (InventoryItemBase)prefab.AddComponent(type);
  16. comp.ID = crudList.Count == ? : crudList[crudList.Count - ].ID + ;
  17. Object.DestroyImmediate(obj);
  18.  
  19. AddItem(comp, true);
  20. };
  21. }

2、地方的包裹是如何对应Item model的,且之间的关系是什么?

我们看到1中的代码创建好刚体,碰撞后的正方体后

var comp = (InventoryItemBase)prefab.AddComponent(type);

通过AddComponent添加了用户选择的Type,通过类型转换(InventoryItemBase)我们知道这个类型是Item类型。

然后我们再通过Unity3d 可视化环境来验证一下

通过选中预设我们看到其绑定的相关插件有碰撞和刚体属性,最后绑定的脚本是Consumable Inventory Item (Script),这样也验证了上面代码加入的Type,也就是在类选择所对应的InventoryItemBase 类型

这里需要注意的是Object Triggerer Item脚本是如何绑定到对象上的,这块是一个小技巧,我找了半天才发现的

/// <summary>
/// The base item of all the inventory items, contains some default behaviour for items, which can (almost) all be overriden.
/// </summary>
[RequireComponent(typeof(ObjectTriggererItem))]
public partial class InventoryItemBase : MonoBehaviour

妈蛋的终于有解决上帝之手的方法了,用RequireComponent这个特性就可以不用手动进行相关插件的绑定了。

上图是Consumable Inventory Item(script)的public field详情了,是不是似曾相识,就是和Item Editor工具创建Prefab的时候是一样的。

到此第二个问题回答完毕。

3、拾取的过程是怎么样的?

在正式回答前,我先yy下,既然拾取必须是双向,而且应该是触发的(当点击鼠标触发),然后Play接收到触发的调用进行拾取,最后清理空背包(立方体消失),下面去看看代码是否是这么实现的。

触发器这里在2的答案里已经有了,看了下做法出奇的简单,可能这就是框架的力量吧,下面贴出源码

  1. /// <summary>
  2. /// Used to trigger item pickup, modify the settings in ShowObjectTriggerer.
  3. /// </summary>
  4. [AddComponentMenu("InventorySystem/Triggers/Object triggerer item")]
  5. [RequireComponent(typeof(InventoryItemBase))]
  6. [RequireComponent(typeof(Rigidbody))]
  7. public partial class ObjectTriggererItem : MonoBehaviour
  8. {
  9.  
  10. public InventoryItemBase item { get; protected set; }
  11.  
  12. public bool inRange
  13. {
  14. get
  15. {
  16. return Vector3.Distance(InventorySettingsManager.instance.playerObject.transform.position, transform.position) < InventorySettingsManager.instance.useObjectDistance;
  17. }
  18. }
  19.  
  20. public void Awake()
  21. {
  22. item = GetComponent<InventoryItemBase>();
  23. }
  24.  
  25. public virtual void OnMouseDown()
  26. {
  27. if (ShowObjectTriggerer.instance != null && ShowObjectTriggerer.instance.itemTriggerMouseClick && InventoryUIUtility.clickedUIElement == false)
  28. {
  29. if (inRange)
  30. Use();
  31. else
  32. {
  33. InventoryManager.instance.lang.itemCannotBePickedUpToFarAway.Show(item.name, item.description);
  34. }
  35. }
  36. }
  37.  
  38. protected virtual void Use()
  39. {
  40. item.PickupItem();
  41. }
  42. }

这里我们很容易看到了OnMouseDown触发的物品拾取逻辑,直接调用绑定的InventoryBaseItem的PickupItem()拾取函数即可,这里再次重温下自动绑定的威力

[RequireComponent(typeof(InventoryItemBase))]

当需要使用的时候记得在Awake()函数中设置相关属性即可

public void Awake()
{
    item = GetComponent<InventoryItemBase>();           
}

  1. /// <summary>
  2. /// Pickups the item and stores it in the Inventory.
  3. /// </summary>
  4. /// <returns>Returns 0 if item was stored, -1 if not, -2 for some other unknown reason.</returns>
  5. public virtual bool PickupItem(bool addToInventory = true)
  6. {
  7. if(addToInventory)
  8. return InventoryManager.AddItem(this);
  9.  
  10. return true;
  11. }

上面是InventoryItemBase中的PickupItem方法,只用调用InventoryMannager类的静态方法AddItem方法即可,就是这么简单

  1. /// <summary>
  2. /// Add an item to an inventory.
  3. /// </summary>
  4. /// <param name="item">The item to add</param>
  5. /// <returns></returns>
  6. public static bool AddItem(InventoryItemBase item, bool repaint = true)
  7. {
  8. if (CanAddItem(item) == false)
  9. {
  10. instance.lang.collectionFull.Show(item.name, item.description, instance.inventory.collectionName);
  11. return false;
  12. }
  13.  
  14. //// All items fit in 1 collection
  15. //if (item.currentStackSize <= item.maxStackSize)
  16. // return best.collection.AddItem(item, repaint);
  17.  
  18. // Not all items fit in 1 collection, divide them, grab best collection after each iteration
  19. // Keep going until stack is divided over collections.
  20. while (item.currentStackSize > )
  21. {
  22. var bestCollection = instance.GetBestLootCollectionForItem(item, false).collection;
  23. uint canStoreInCollection = bestCollection.CanAddItemCount(item);
  24.  
  25. var copy = GameObject.Instantiate<InventoryItemBase>(item);
  26. copy.currentStackSize = (uint)Mathf.Min(Mathf.Min(item.currentStackSize, item.maxStackSize), canStoreInCollection);
  27. bestCollection.AddItem(copy);
  28.  
  29. item.currentStackSize -= copy.currentStackSize;
  30. //item.currentStackSize = (uint)Mathf.Max(item.currentStackSize, 0); // Make sure it's positive
  31. }
  32.  
  33. Destroy(item.gameObject); // Item is divided over collections, no longer need it.
  34.  
  35. return true;
  36. }

InventoryMannager中的AddItem,代码看似简单,却有四个逻辑,是否可以放置,选择最佳容器,叠放逻辑,销毁。

问题3回答完毕走人

Inventory Pro 装备拾取的实现的更多相关文章

  1. Unity3D 装备系统学习Inventory Pro 2.1.2 总结

    前言 写在最前面,本文未必适合纯新手,但有一些C#开发经验的还是可以看懂的,虽然本人也是一位Unity3D新人,但是本文只是自己在学习Inventory Pro的学习总结,而不是教程,本人觉得要读懂理 ...

  2. Unity3D 装备系统学习Inventory Pro 2.1.2 基础篇

    前言 前一篇 Unity3D 装备系统学习Inventory Pro 2.1.2 总结 基本泛泛的对于Inventory Pro 这个插件进行了讲解,主要是想提炼下通用装备系统结构和类体系.前两天又读 ...

  3. 通用窗口类 Inventory Pro 2.1.2 Demo1(下续篇 ),物品消耗扇形显示功能

    本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...

  4. 通用窗口类 Inventory Pro 2.1.2 Demo1(下)

    本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...

  5. 通用窗口类 Inventory Pro 2.1.2 Demo1(中)

    本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...

  6. Unity3D 通用提示窗口实现分析(Inventory Pro学习总结)

    背景 游戏中的UI系统或者叫做GUI窗口系统主要有:主要装备窗口(背包,角色窗口也是一种特殊窗口).确实提示窗口(如购买确认).信息提示窗口(一遍没有按钮,ContexntMenu)和特殊窗口(聊天记 ...

  7. Unity3d UGUI 通用Confirm确认对话框实现(Inventory Pro学习总结)

    背景 曾几何时,在Winform中,使用MessageBox对话框是如此happy,后来还有人封装了可以选择各种图标和带隐藏详情的MessageBox,现在Unity3d UGui就没有了这样的好事情 ...

  8. 通用窗口类 Inventory Pro 2.1.2 Demo1(上)

    插件功能 按照Demo1的实现,使用插件来实现一个装备窗口是很easy的,虽然效果还很原始但是也点到为止了,本篇涉及的功能用加粗标出,具体的功能如下: 1.实现了两个窗口,通过点击键盘I来,打开或者关 ...

  9. 轻量级ORM框架 Dapper快速学习

    好在有师兄师姐一起带着做,所以开始没那么困难,但是由于大学涉猎范围有限,往往有很尴尬的时候,不懂构造方法重载,去“请教”,本来以为师兄会帮忙写好,结果“我念,你来写”,被深深的激励了一把,后来就早出晚 ...

随机推荐

  1. C# vba 操作 Word

    添加引用 Microsoft Word  *.0 Object Library Microsoft Graph *.0 Object Library 变量说明 Object oMissing = Sy ...

  2. Andrew Ng机器学习公开课笔记–Independent Components Analysis

    网易公开课,第15课 notes,11 参考, PCA本质是旋转找到新的基(basis),即坐标轴,并且新的基的维数大大降低 ICA也是找到新的基,但是目的是完全不一样的,而且ICA是不会降维的 对于 ...

  3. 低功耗蓝牙4.0BLE编程-nrf51822开发(10)-描述符

    特性中的属性有两种:属性值或描述符. 支持通知或指示的特性中默认有一个描述符:客户端特性配置描述符(Client Characteristic Configuration Descriptor,CCC ...

  4. maven--composer---setting.xml(updatepolicy)---mvn install , mvn deploy

    场景:最近再整系统的自动部署流程,由于公司的jar包在svn以及mvn的仓库上都存在,开发人员在开发的过程中都依赖mvn仓库中的Jar 包,在jar上线的时候,配置管理人员把jar 从svn管理的工作 ...

  5. 一个高度压缩的bit位图字典的实现

    微软实现的字典功能简单方便,出于全局性考虑,其内部实现比较复杂,在对海量数据处理时,仅仅存放一个对象地址就将占据32个bit(64位机器中占据64个bit),而且其内部通过int[]来处理hash桶, ...

  6. IOS证书的申请和使用

    苹果的证书繁锁复杂,制作管理相当麻烦,今天决定重置一个游戏项目中的所有证书,做了这么多次还是感觉很纠结,索性直接记录下来,日后你我他查阅都方便: 关于证书 苹果使用密文签名技术来验证App的合法性,不 ...

  7. To do

    小事{ android values public.xml 树.图的所有遍历方式和优劣 } 大事{ 通读android所有官网文档. android多dex多res开发框架. java AOT(and ...

  8. self.nsme 和 _name 的问题

    .h文件 @interface myclass:NSObject @property(nonatomic,retain)NSArray*MyArray; @end .m文件 @implementati ...

  9. HTML5样式和列表、CSS链接的四种状态

    一.HTML5样式 1.标签: <style>:样式定义: <link>:资源引用: 2.属性: type="text/css":引入文档类型: rel=& ...

  10. asp.net mvc 简单搜索功能

    View中代码: <input type="text" class="searchText" id="searchText"/> ...