NGUI背包系统

  背包系统,顾名思义,就是像书包一样存储玩家角色所需的各种物品的系统。我姑且这样描述:一个背包系统有许多物品栏组成,一个物品栏存放一种物品。如下图的背包系统就有16个物品栏。我们需要实现一种简易功能:就是每当一定时机生成一种物品,将物品放到背包系统的界面。再进一步,如果背包中存在的物品和即将放入的物品是同一种时,只更改该物品的数量;如果背包中不存在即将放入的物品,则在背包中增加该物品,放入的位置是按空位置依次放入,不能随机乱放。如下图所示,每个物品栏右下角为物品的数量。

  现在写这篇文章的时候,逻辑我还没有捋的很清晰。等我写完,不止我,各位看官相信也会不在感到迷茫了。我们的背包系统是16个单元格组成的,cell 1~16。实现背包系统的底层支持,其实得益于NGUI的UIDragDropItem脚本,通过类名我们可以明白这就是关于拖拽功能的一个脚本,我们需要做的就是要继承该类,重写一个事件处理函数OnDragDropRelease(GameObject surface),该函数的主要作用是:当我们拖拽物品放下(Release)时,此函数会被触发。但是,

(1)被拖拽的物品必须添加这样一种脚本,脚本继承自UIDragDropItem脚本类。

(2)被拖拽的物品必须添加碰撞体,NGUI交互必须添加碰撞体。

(3)物品所要放置的UI对象也必须加上碰撞体,理由如上相同。

  所以,cell1~cell16这16个UI游戏对象都必须添加上碰撞体。它们的功能都是相同的,都是接受物品拖放的。当多个游戏对象的功能相同时,U3d告诉我们,最好把他们保存为Prefab,所以cell预设体也就产生了。

  而物品的功能我们也能够很自然的想到了,就是能够实现拖拽功能,并且能够接收拖拽释放后的事件,做出一些事件处理。我们把物品保存也保存为预设体,KnapsackItem预设体。OnDragDropRelease(GameObject surface)函数是实现的细节。。。。。。将物品放入物品栏的中心;当一个物品放入另一个含有其它物品的物品栏中时,两种物品对换;物品栏中的物品增加时,物品的下标(数量)实时变更。还有一个我自己添加的功能,感觉没什么用处,就是将一个物品拖入另一个含有相同物品的物品栏时,两个物品合并,物品下标(数量)增加。

  下图为背包系统的层级视图和对应的Scene视图的内容。

  该预设体包含了这样一个脚本,KnapsackItem.cs。该脚本可以实现将物品放入背包,并且当拖入的目标对象中有其它物品时,将两个物品互换。此时,我们就实现了将一个物品栏中的物品放入其它物品栏的功能。

  以上只是背包系统的一种功能,将背包中已有的物品更换物品栏,或是交换两个物品栏中的物品。我们还应该增加一个功能:增加物品。在这里,我们无法像在具体游戏那样增加物品,所以我们采用每按一个按键,物品栏中就会随机多出一个物品的方法(测试方法)。

  我们想一想增加物品应该放在哪一个游戏对象的脚本中呢?

  增加物品,应该是物品栏增加物品,所以,此函数应该包含在象征着物品栏的游戏对象上挂在的脚本的一个方法。我们一调用该方法,就会在物品栏中按照一定规则增加物品。脚本名我们定义为Knapsack.cs脚本,该脚本定义一个public类型的方法:PickUp()。我们慢慢思考,一点点扩展功能。首先,最简单的思路就是,我们每按下X键就会忘背包系统中增加一个物品,增加物品的物品栏是有优先级的,我们认为cell1的优先级最高。每执行一次该函数,就应该从cell1开始遍历到cell16,当物品栏为空时,我们就忘该物品栏增加一个物品,增加物品的函数是NGUI提供给我们的,NGUITools.AddChild(itemParent.gameObject, item);我感觉该函数的作用应该就是使用GameObject的Instantiate函数创建出一个item,并且将item作为第一个参数itemParent.gameObject游戏对象的子对象,仅此而已。我们要记得改换物品的sprite,以及break退出该循环以保证这是我们一次增加物品,如果没有break,所有为空的物品栏都会填充上item,这并不是我们想要看到的结果。

  到此为止,我们这个背包系统是不是感觉非常的蛋疼,因为很多相同的物品放在了不同的物品栏中。我们想要得到的结果是每个物品栏存放相同的物品,物品需要有数量标识。

  下面让大家看看我们实现的比较蛋疼的背包系统吧。

  牢骚就此打住,我们还是想一想应该如何改进吧。在向物品栏中增加item之前,我们必须判断物品栏中是不是有与将要添加的物品相同的物品,如果有的话,直接增加其数量值即可,也省了增加物品的不必要的开销了。一个小技巧就是在PickUp函数中增加一个标识变量 bool hasTheSame,一开始该变量为false,一旦物品栏中有相同物品时,执行增加物品数量的操作,并且hasTheSame变为true。将刚刚我们实现的往空物品栏中增加物品的代码放入 if(!hasTheSame){ }中就好了。下面我附上Knapsack.cs和KnapsackItem.cs脚本,让大家看一下,有不足之处请大家指正。

 1 using UnityEngine;
 2 using System.Collections;
 3
 4 public class Knapsack : MonoBehaviour {
 5     public GameObject item;
 6     public string[] itemNames;
 7     // Use this for initialization
 8     void Start () {
 9
10     }
11
12     // Update is called once per frame
13     void Update () {
14         if (Input.GetKeyDown(KeyCode.X))
15         {
16             PickUp();
17         }
18     }
19     /// <summary>
20     /// 该函数将获取一个物品
21     /// 依次遍历各个单元格,如果要加入的物品在物品栏中已经存在,则只需要在将物品栏中存在的物品的数量增加即可
22     /// 如果要加入的物品不存在的话,添加该物品
23     /// 通过一个标志位来判断属于上面哪种情况
24     /// </summary>
25     public void PickUp()
26     {
27         bool hasTheSame = false;
28         int index = Random.Range(0, 3);
29
30         //for (int i = 0; i < transform.childCount; i++)
31         //{
32         //    //itemParent表示物品要摆放的窗口
33         //    Transform itemParent = transform.GetChild(i);
34
35         //    //如果要加入的物品在物品栏中已经存在,则只需要在将物品栏中存在的物品的数量增加即可
36         //    if (itemParent.childCount > 0)
37         //    {
38         //        //print(itemParent.GetComponent<UISprite>().spriteName);
39         //        //print(itemParent.GetComponentInChildren<UISprite>().spriteName);
40         //        if (itemParent.GetChild(0).GetComponent<UISprite>().spriteName == itemNames[index])
41         //        {
42         //            //itemParent.GetComponentInChildren<KnapsackItem>().AddCount(1);
43         //            itemParent.GetChild(0).GetComponent<KnapsackItem>().AddCount(1);
44         //            hasTheSame = true;
45         //            break;
46         //        }
47         //    }
48         //}
49         //如果物品栏没有相同的物品
50         if (!hasTheSame)
51         {
52             for (int i = 0; i < transform.childCount; i++)
53             {
54                 //itemParent表示物品要摆放的窗口
55                 Transform itemParent = transform.GetChild(i);
56
57                 if (itemParent.childCount == 0)
58                 {
59                     //向一个游戏对象中添加子对象,该子对象是预设体Prefab
60                     GameObject go = NGUITools.AddChild(itemParent.gameObject, item);
61                     go.GetComponent<UISprite>().spriteName = itemNames[index];
62                     go.transform.localPosition = Vector3.zero;
63
64                     break;
65                 }
66             }
67         }
68
69     }
70 }

 1 using UnityEngine;
 2 using System.Collections;
 3
 4 //使用继承UIDragDropItem类
 5 public class KnapsackItem : UIDragDropItem
 6 {
 7
 8     public UISprite selfSprite;
 9     public UILabel numberLabel;
10     int count = 1;
11
12     public void AddCount(int value)
13     {
14         count += value;
15         numberLabel.text = count.ToString();
16     }
17
18     protected override void OnDragDropRelease(GameObject surface)
19     {
20         base.OnDragDropRelease(surface);
21         //如果拖拽的目标对象没有子对象,则直接变为目标对象的子物体,在目标对象的坐标系中归零
22         if (surface.tag == "cell")
23         {
24             transform.parent = surface.transform;
25             transform.localPosition = Vector3.zero;
26             //如果拖拽的目标对象为Cell的子对象,因为子对象的depth大,在上面,并且有Collider组件
27             //此时应该交换两个物品item
28         }else if(surface.tag == "item"){
29             //合并两个相同的物品
30             if (transform.GetComponent<UISprite>().spriteName == surface.GetComponent<UISprite>().spriteName)
31             {
32                 transform.parent = surface.transform.parent.transform;   //surface表示物品
33                 transform.localPosition = Vector3.zero;
34                 Destroy(surface);
35                 AddCount(1);
36             }
37             else
38             {
39                 Transform newParent = surface.transform.parent;    //新旧父亲是相对于拖动的物品的。
40                 Transform oldParent = transform.parent;
41                 surface.transform.parent = oldParent;
42                 surface.transform.localPosition = Vector3.zero;
43                 transform.parent = newParent;
44                 transform.localPosition = Vector3.zero;
45             }
46         }
47     }
48 }

  最后,总结一下背包系统的要点:

  (1)需要拖拽的物品需要添加继承自UIDragDropItem.cs的脚本类,并且需要重写OnDragDropRelease()函数。需要实现的功能为:物品栏为空时物品拖入物品栏中心位置、物品栏中已有物品并且与需要拖拽的物品相同时增加物品数量、物品栏中已有物品并且与需要拖拽的物品不相同时交换两个物品。

  (2)物品对象和物品栏对象必须加上碰撞体组件才能实现拖拽功能。

  (3)另外需要一个脚本类来实现物品动态增加的功能。也是从物品栏为空时、不为空的角度来考虑。到底是从无到有还是直接对已有的物品增加数量,就看各位看官的能耐啦。

         

时间: 2024-10-12 15:20:48

NGUI背包系统的相关文章

unity3d 项目源码下载链接

2-1 炉石传说 客户端加服务器端 链接:http://pan.baidu.com/s/1dDKY3Fr 密码:c03q 2-2 新仙剑奇侠传 链接:http://pan.baidu.com/s/1b4QVqI 密码:dic5 2-3 unity3d 战斗卡牌<变身吧主公>客户端+服务器源码 链接:http://pan.baidu.com/s/1kUpot51 密码:i02u 2-4 降临OL-U3D全套源码 链接:http://pan.baidu.com/s/1sktLQ5v 密码:we0g

工程源码目录

以下资源全部为网络搜集所得,仅供学习研究,严谨用于商业行为,请下载后于24小时之内删除. 2-1    炉石传说 客户端加服务器端 链接:http://pan.baidu.com/s/1dDKY3Fr 密码:c03q 2-2    新仙剑奇侠传 链接:http://pan.baidu.com/s/1b4QVqI 密码:dic5 2-3    unity3d 战斗卡牌<变身吧主公>客户端+服务器源码 链接:http://pan.baidu.com/s/1kUpot51 密码:i02u 2-4  

Unity3D工程源码目录

2-1    炉石传说 客户端加服务器端 链接:http://pan.baidu.com/s/1dDKY3Fr 密码:c03q 2-2    新仙剑奇侠传 链接:http://pan.baidu.com/s/1b4QVqI 密码:dic5 2-3    unity3d 战斗卡牌<变身吧主公>客户端+服务器源码 链接:http://pan.baidu.com/s/1kUpot51 密码:i02u 2-4    降临OL-U3D全套源码 链接:http://pan.baidu.com/s/1skt

NGUI简单背包系统的实现

一.利用txt文件存储游戏物品信息 首先在asset下创建一个txt文件,这里我们命名为objectsInfoList.txt,并将其拖放到unity Project视图中. 其中txt中我们先存放一些物品信息,每行存储一种物品信息,分别为编号.名称.物品对应的图片名.种类.回血值.回蓝值.出售价和购买价. 其中物品图片要先用NGUI做成图集,种类中的Drug为药品类,以后在代码中我们会定义一个枚举用于存储物品种类. 接下来我们创建一个空物体叫做GameSetting,上面挂一个脚本Object

Unity3D使用NGUI实现简单背包功能

前话 在许多类型游戏中我们经常会使用到背包,利用背包来设置相应角色属性,多了背包也会让游戏增色拓展不少. 那在Unity3D游戏开发中该如何编写背包系统呢?因为有高人开发了NGUI插件,因此我们进行简单编写代码设置即可实现一个简单的背包功能了. 准备工作 新建一个工程PackageDemo 导入NGUI包(最新版3.9.8版的正版89刀) 准备好图片素材,使用NGUI将其打包成图集 背包 背包格子 物品 简单背包功能实现 第一步,添加NGUI控件,使用素材 项目目录以及场景列表如下: 要注意的是

【学习中】Unity插件之NGUI 完整视频教程

课程 章节 内容 签到 Unity插件之NGUI 完整视频教程 第一章 NGUI基础控件和基础功能学习 1.NGUI介绍和插件的导入 6月29日 2.创建UIRoot 6月29日 3.学习Label控件,显示文字 6月29日 4.学习Sprite创建精灵,显示图片 5.学习Panel面板,控件容器 6.创建Button按钮,使用脚本监听按下 7.创建图集Atlas 8.切图SlicedSprite九宫切图 9.dynamicFont动态字体制作和显示 10.widget属性,pivot,dept

unity背包系统(摘抄)

新的背包系统包括: 1.一个用于表示背包系统的按钮: 该按钮上添加了EventListener事件,该事件经过改写,可用于实现点击一次展示,点击第二次消失的效果. 代码比较简单,主要是在EventListener本身的事件代码上进行了一定的修改: public GameObject item;public GameObject tip;public int count = 0; 其中Item用于表示监听的物体,tip表示受到监听后发生动作的物体,count用于计数,以便于实现点击两次后tip物体

【Unity】基于MVC模式的背包系统 UGUI实现

本文基于MVC模式,用UGUI初步实现了背包系统. 包含点击和拖拽两种逻辑,先献上源代码,工程和分析稍后补充. Model 层 using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; /// <summary> /// 脚本功能:MVC模式--Model层,定义物品结构,保存物品数据 /// 添加对象:Bag 背包(Canvas下的空对象) ///

Unity插件之NGUI学习(4)—— 创建UI2DSprite动画

创建一个新的Scene,并按 Unity插件之NGUI学习(2)创建UI Root,并在UI Root的Camera下创建一个Panel. 然后在选中Panel,在菜单中选择NGUI->Create->Unity 2D Sprite 查看Inspector窗口 接着是在Unity中制作Sprite: 在Project窗口创建Textures文件夹,并从外部拖入一些图片素材,然后选中需要转成Sprite的图片,然后在Inspector窗口进行转变Sprite的操作,如图. 选择Sprite(2D