网站公告 | 泰斗网校全新上线了,可以和论坛用户登录同步,如果遇到登录问题联系管理员解决
查看: 6002|回复: 14
收起左侧

[啦啦酱] [3D UI 之道具系统系列] 4. 简单的交易系统 (3)(完)

[复制链接]

[啦啦酱] [3D UI 之道具系统系列] 4. 简单的交易系统 (3)(完)[复制链接]

quincyhuanghk 发表于 2015-9-3 08:06:00 [显示全部楼层] 回帖奖励 |倒序浏览 |阅读模式 回复:  14 浏览:  6002
本帖最后由 quincyhuanghk 于 2015-9-2 09:43 编辑

茶水君干货系列,小白必学,大神必喷。
首发泰斗,https://www.taidous.com,欢迎转发,请注明出处哦,违者,我也有没办法。

本章几乎纯数据,请有心理准备。

[3D UI 之道具系统系列] 4. 简单的交易系统 (3)(完)

那么,今天,我们就来KO掉最后那两个的UI面板吧,
至于面板的设计,我们以前就做好了,所以,这次我们直接设计面板的代码吧,首先是商店的面板,UIShopping,,图1,


(说明写在注释里面了)代码:
[C++] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class UIShopping : UIStorageBase {

        // 拒绝列表,处于拒绝列表中的道具类型,不能被进行出售操作。
        // PS: 可以自定义NPC可交易的道具项目和类型
        public List<ItemBase.Type> rejectType;

        // Use this for initialization
        void Start () {
                if (GetComponent<Collider>() == null)
                {
                        Debug.LogError("Require a collider");
                }
                // 初始化UISlot,和赋值索引号。
                Assign_Slot();
                // 同步数据模型和UISlot
                Sync();
        }
        // Update is called once per frame
        void Update () {
                
        }

        // 同步数据模型和UISlot
        override public void Sync()
        {
                // 清空UIslot
                for(int i=0;i<slots.Count;i++)
                {
                        slots[i].SetIconEmpty();
                }
                
                if (backpackSys)
                {
                        // 获取背包数据系统,
                        ItemSlot[] item_ids = backpackSys.backpack.Get_All_Item();
                        for(int i=0; 
                            i<item_ids.Length && i<slots.Count; 
                            i++)
                        { 
                                // 如果当前道具是空道具,则忽略
                                ItemBase item = ItemDatabase.GetItem(item_ids[i].Get_Item_ID());
                                if (item == null)
                                        continue;

                                // 同步UISlot的数据
                                slots[i].SetItemID(item.item_id);
                                slots[i].SetAtt1(item.att1);
                                slots[i].SetColor(item.color);
                                slots[i].SetIcon(item.icon);

                                // 修正文本的显示
                                if (item.maxStack > 1)
                                {
                                        slots[i].SetInfo("$ " + item.buy * item.maxStack + " ["+item.maxStack+"]");
                                }
                                else
                                {
                                        slots[i].SetInfo("$ " + item.buy);
                                }

                                // 打开拖放功能
                                slots[i].SetDragbale(true);
                        }
                }
        }
        
        // this is called by slot, need to assign to slot first
        override public void Slot_OnClick(int id)
        {
                
        }
        
        // this is called by slot, need to assign to slot first
        // 鼠标滑入,在描述面板中显示
        override public void Slot_OnEnter(int id)
        {
                if (descrption)
                {
                        ItemBase item = ItemDatabase.GetItem(slots[id].item_id);
                        if (item != null)
                        {
                                string info = "["+item.displayName +"]\n\n"+ item.comment;
                                descrption.Set(slots[id],info);
                        }
                        
                }
        }
        
        // this is called by slot, need to assign to slot first
        // 鼠标滑出,则清空描述
        override public void Slot_OnExit(int id)
        {
                if (descrption)
                {
                        descrption.Set(null,"");
                }
        }
        
        // this function will be called by slot of other storage, when the slot be dropped on this storage
        // 负责处理和UISolt的交互
        override public void Income_Slot(UISlot slot)
        {
                // 如果UISlot不是属于本面板
                if (slot.storage != this)
                {
                        // sell from UIBackpack
                        // 如果UISlot属于背包面板的,这里的背包面板UIBackpack是玩家的背包面板
                        if (slot.storage.GetType() == typeof(UIBackpack))
                        {
                                // 出售道具
                                Sell(slot);
                        }
                }

                
        }

        // 出售道具
        void Sell(UISlot slot)
        {
                // 通过数据库查询道具,因为空的UISlot不能被拖放,所以这里就不判断空道具了
                ItemBase item = ItemDatabase.GetItem(slot.item_id);
                
                // reject
                // 该道具是否属于被拒绝的类型
                foreach(ItemBase.Type t in rejectType)
                {
                        if (t == item.type)
                                return;
                }

                // 获取作为通货的道具
                ItemBase money = ItemDatabase.GetItem(moneyID);
                // 获取当前UISlot中的道具数量
                int sellStatk = slot.storage.backpackSys.backpack.Get_Stack(slot.slot_id);
                // add money and remove the item to/from slot.storage
                // 为那个传进来的UISlot所属的面板的背包系统中的背包添加适当的通货,同时移除道具。
                // 说人话就是,为玩家背包添加金钱,移除出售了的道具。
                slot.storage.backpackSys.backpack.Add(money.item_id, item.sell*sellStatk);
                slot.storage.backpackSys.backpack.Remove(slot.slot_id,item.item_id,sellStatk);
                // sync
                // 同步双方的面板和数据
                slot.storage.Sync();
                Sync();
        }
}



这里值得注意的是,每个UI面板都关联一个背包系统。但是我们玩家有背包和装备栏,所以在UI面板中需要按需求分开处理了,下面就是玩家的背包UI和装备UI了。

UIBackpack,,如图2,

代码:
[C++] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class UIBackpack : UIStorageBase {


        // Use this for initialization
        void Start () {
                if (GetComponent<Collider>() == null)
                {
                        Debug.LogError("Require a collider");
                }
                // 初始化UISlot,和赋值索引号。
                Assign_Slot();
                // 同步数据模型和UISlot
                Sync();
        }
        
        // Update is called once per frame
        void Update () {
        
        }

        // 同步数据模型和UISlot
        override public void Sync()
        {
                // 清空UIslot
                for(int i=0;i<slots.Count;i++)
                {
                        slots[i].SetIconEmpty();
                }


                if (backpackSys)
                {
                        // 获取背包数据系统,
                        ItemSlot[] item_ids = backpackSys.backpack.Get_All_Item();
                        for(int i=0; 
                            i<item_ids.Length && i<slots.Count; 
                            i++)
                        {
                                // 如果当前道具是空道具,则忽略
                                ItemBase item = ItemDatabase.GetItem(item_ids[i].Get_Item_ID());
                                if (item == null)
                                        continue;

                                // 同步UISlot的数据
                                slots[i].SetItemID(item.item_id);
                                slots[i].SetAtt1(item.att1);
                                slots[i].SetColor(item.color);
                                slots[i].SetIcon(item.icon);
                                slots[i].SetInfo(backpackSys.backpack.Get_Stack(i)+"");

                                // 打开拖放功能
                                slots[i].SetDragbale(true);
                        }
                }
        }

        // this is called by slot, need to assign to slot first
        // 鼠标双击,如果道具是消耗类型的,则使用它。数量-1
        override public void Slot_OnClick(int id)
        {
                //Debug.Log("Slot " + id + " on click!");
                // use item
                ItemBase item = ItemDatabase.GetItem(slots[id].item_id);
                if (item.type == ItemBase.Type.Item_Consumable)
                {
                        // use it
                        backpackSys.backpack.Remove(id,item.item_id,1);
                        Sync();
                }
        }
        
        // this is called by slot, need to assign to slot first
        // 鼠标滑入,在描述面板中显示
        override public void Slot_OnEnter(int id)
        {
                if (descrption)
                {
                        ItemBase item = ItemDatabase.GetItem(slots[id].item_id);
                        if (item != null)
                        {
                                string info = "["+item.displayName +"]\n\n"+ item.comment + "\n$ " + item.sell;
                                descrption.Set(slots[id],info);
                        }

                }
        }
        
        // this is called by slot, need to assign to slot first
        // 鼠标滑出,则清空描述
        override public void Slot_OnExit(int id)
        {
                if (descrption)
                {
                        descrption.Set(null,"");
                }
        }
        
        // this function will be called by slot of other storage, when the slot be dropped on this storage
        // 负责处理和UISolt的交互
        override public void Income_Slot(UISlot slot)
        {
                //Debug.Log("Slot income: " + slot.slot_id);
                // 如果UISlot不是属于本面板
                if (slot.storage != this)
                {
                        // buy from UI Shopping
                        // 如果面板属于商店,执行买操作,
                        if (slot.storage.GetType() == typeof(UIShopping))
                        {
                                Buy(slot);
                        }
                        
                        // unequip
                        // 如果面板属于装备,执行卸载操作
                        if (slot.storage.backpackSys == this .backpackSys && slot.storage.GetType() == typeof(UIEquipment))
                        {
                                
                                Unequip(slot);
                        }
                }
                // 如果UISlot是属于本面板
                else
                {
                        // do exchange
                        // 交换/合并分栏
                        Exchange(slot);
                }
                
        }

        // 交换/合并分栏
        void Exchange(UISlot slot)
        {
                ItemBase item = ItemDatabase.GetItem(slot.item_id);
                UISlot us = Get_UISlot_On_End_Drag();
                if (us != null)
                {
                        if (us.slot_id != slot.slot_id)
                        {
                                backpackSys.backpack.ExChange(us.slot_id, slot.slot_id);

                                Sync();
                        }
                
                }
        }

        // 买操作
        void Buy(UISlot slot)
        {
                // 通过数据库查询道具,因为空的UISlot不能被拖放,所以这里就不判断空道具了
                ItemBase item = ItemDatabase.GetItem(slot.item_id);

                // 获取本面板中的被交互的UISlot
                UISlot uis = Get_UISlot_On_End_Drag();
                if (uis != null)
                {
                        // enougth money
                        // 是否有足够的通货买道具,
                        // 每次买卖一组道具,通过for循环来购买,每次购买一个,直到钱不足或满足购买数量。
                        for(int i=0;i<item.maxStack; i++)
                        {
                                // 判断是否有足够的钱购买一个道具
                                if (backpackSys.backpack.Get_Stack(slot.storage.moneyID) >= item.buy)
                                {
                                        // 是否有足够的空间购买道具
                                        if (backpackSys.backpack.Add(uis.slot_id,item.item_id,1) == 1)
                                        {
                                                // 勾除响应的通货
                                                backpackSys.backpack.Remove(slot.storage.moneyID,item.buy);
                                        }
                                        else
                                        {
                                                break;
                                        }
                                }
                                else
                                {
                                        break;
                                }
                        }
                        // 同步双方的面板
                        slot.storage.Sync();
                        Sync();
                }

        }

        // 卸载
        void Unequip(UISlot slot)
        {
                // 获取本面板中的被交互的UISlot
                UISlot uis = Get_UISlot_On_End_Drag();
                if (uis != null)
                {
                        // 是否有足够的空位放卸载的道具
                        if (backpackSys.backpack.Add(uis.slot_id,slot.item_id,1) == 1)
                        {
                                // 移除装备栏中的道具
                                backpackSys.equipment.Remove(slot.slot_id,slot.item_id,1);
                        }
                        // 同步双方的面板
                        Sync();
                        slot.storage.Sync();
                }

        }
}

UIEquipment, 如图3,


代码:
[C++] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class UIEquipment : UIStorageBase {

        // 装备的类型,对应UISlot的索引,
        // 例如第0个Slot是武器栏,第1个Slot是防具。
        public List<ItemBase.Type> itemTypes;

        // Use this for initialization
        void Start () {
                if (GetComponent<Collider>() == null)
                {
                        Debug.LogError("Require a collider");
                }
                // 初始化UISlot,和赋值索引号。
                Assign_Slot();
                // 同步数据模型和UISlot
                Sync();
        }
        
        // Update is called once per frame
        void Update () 
        {
        
        }

        // 同步数据模型和UISlot
        override public void Sync()
        {
                // 清空UIslot
                for(int i=0;i<slots.Count;i++)
                {
                        slots[i].SetIconEmpty(); 
                }
                
                if (backpackSys)
                {
                        // 获取背包数据系统,
                        ItemSlot[] item_ids = backpackSys.equipment.Get_All_Item();
                        for(int i=0; 
                            i<item_ids.Length && i<slots.Count; 
                            i++)
                        {
                                // 如果当前道具是空道具,则忽略
                                ItemBase item = ItemDatabase.GetItem(item_ids[i].Get_Item_ID());
                                if (item == null)
                                        continue;

                                for(int j=0; j< itemTypes.Count && j<slots.Count; j++)
                                {
                                        // 对应装备栏的可装备类型
                                        if (item.type == itemTypes[j])
                                        {
                                                slots[j].SetItemID(item.item_id);
                                                slots[j].SetAtt1(item.att1);
                                                slots[j].SetColor(item.color);
                                                slots[j].SetIcon(item.icon);
                                                //slots[i].SetInfo("$ " + item.buy);
                                                // 打开拖放功能
                                                slots[j].SetDragbale(true);
                                                break;
                                        }
                                }
                        }
                }
        }

        // this is called by slot, need to assign to slot first
        override public void Slot_OnClick(int id)
        {

        }

        // this is called by slot, need to assign to slot first
        // 鼠标滑入,在描述面板中显示
        override public void Slot_OnEnter(int id)
        {
                if (descrption)
                {
                        ItemBase item = ItemDatabase.GetItem(slots[id].item_id);
                        if (item != null)
                        {
                                string info = "["+item.displayName +"]\n\n"+ item.comment;
                                descrption.Set(slots[id],info);
                        }
                        
                }
        }
        
        // this is called by slot, need to assign to slot first
        // 鼠标滑出,则清空描述
        override public void Slot_OnExit(int id)
        {
                if (descrption)
                {
                        descrption.Set(null,"");
                }
        }
        
        // this function will be called by slot of other storage, when the slot be dropped on this storage
        // 负责处理和UISolt的交互
        override public void Income_Slot(UISlot slot)
        {
                // 如果UISlot不是属于本面板
                if (slot.storage != this)
                {
                        // slot from this sys
                        // 如果双方同属于一个背包系统,即(玩家背包),执行装备操作
                        if (slot.storage.backpackSys == this.backpackSys)
                        {
                                Equip_Item(slot);
                        }
                }

        }

        // exchange item
        // 装备
        void Equip_Item(UISlot slot)
        {
                // 通过数据库查询道具,因为空的UISlot不能被拖放,所以这里就不判断空道具了
                ItemBase item = ItemDatabase.GetItem(slot.item_id);
                // 获取本面板中的被交互的UISlot
                UISlot us = Get_UISlot_On_End_Drag();
                if (us != null)
                {
                        // 获取本方Slot索引号
                        int index = slots.IndexOf(us);

                        // 装备类型是否符合
                        if (item.type == itemTypes[index])
                        {
                                // 获取旧的道具信息
                                ItemSlot oldItem = backpackSys.equipment.Get_Item_By_Index(us.slot_id);
                                // un equip
                                bool canEquip = true;
                                // 是否有卸载的必要
                                if (oldItem.Get_Item_ID()!= "")
                                {
                                        // 是否有足够的空间卸载
                                        if (backpackSys.backpack.Add(oldItem.Get_Item_ID(),1) == 1)
                                        {
                                                // 卸载旧装备
                                                backpackSys.equipment.Remove(us.slot_id,oldItem.Get_Item_ID(),1);
                                        }
                                        else
                                        {
                                                // 卸载失败,不能执行装备操作
                                                canEquip = false;
                                        }
                                }

                                // equip
                                // 是否可以装备
                                if (canEquip)
                                {
                                        // 是否装备成功
                                        if (backpackSys.equipment.Add(us.slot_id,slot.item_id,1) == 1)
                                        {
                                                // 从背包中移除当前装备
                                                backpackSys.backpack.Remove(slot.slot_id,slot.item_id,1);
                                        }
                                }
                                else
                                {

                                }
                                // 同步双方面板
                                Sync();
                                slot.storage.Sync();
                        }
                }

        }
}


那么,脚本都有,回到我们的编辑器中,为对应的UI面板挂上我们的脚本吧,
那么对于Shopping,我们挂上UIShopping,并做如下配置,图4

Backpack sys就关联我们的那个商店对象吧,
Descrption就是关联我们的那个描述面板。
Money ID就是通货的道具ID。

对于玩家的背包,和装备栏,如图5,6

对于装备面板的配置,这里我们测试量2种类型的装备,武器和护甲,所以对应Slots的size为2,我们的item types的size也为2,这里一定要注意,要一一对应的,否则会有惊喜的。

那么,就大功告成了,图7,

这样子,本系列的基本的道具系统和UI就已经准备好,如果你以为这样就结束了,那就错了,我们可以在此系统的基础上,扩展出后续的功能,例如道具的分解和合成及其对应的面板,相比很多游戏都会有这样的一个系统,来丰富道具系统的特色吧。

那么,下个系列将会分享一下道具系统中的分解和合成。

本系列完。
游客,如果您要查看本帖隐藏内容请回复

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
+1
6009°C
14
  • 西mumu
  • 波波BY
  • hahahuohuo
  • hahahuohuo
  • xiaoyu111
过: 他们

本帖被以下淘专辑推荐:

因分享而快乐,学习以自强!
西mumu 发表于 2015-9-4 09:41:34 显示全部楼层
学习中,努力克服困难
因分享而快乐,学习以自强!
波波BY 发表于 2015-9-7 22:46:28 显示全部楼层
很想学习这种类型的
因分享而快乐,学习以自强!
hahahuohuo 发表于 2015-10-5 18:32:31 显示全部楼层
顶顶顶顶顶顶顶顶
因分享而快乐,学习以自强!
hahahuohuo 发表于 2015-10-6 11:48:44 显示全部楼层
ToHexStringRGBA  报错  ,这方法没有找到
因分享而快乐,学习以自强!
xiaoyu111 发表于 2015-12-13 22:06:41 显示全部楼层
感谢!!!!!!!!!!!!!!!!!!!!!
因分享而快乐,学习以自强!
3182684016 发表于 2015-12-14 18:54:45 显示全部楼层
赞一个!!!学习
因分享而快乐,学习以自强!
q283215159 发表于 2016-1-16 21:51:03 显示全部楼层
附件都是一样的?
因分享而快乐,学习以自强!
jiangzi 发表于 2016-1-24 23:32:14 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
因分享而快乐,学习以自强!
U3D_谢建鸣 发表于 2016-3-25 14:06:01 显示全部楼层
谢谢楼主的分享,下载过来看看
因分享而快乐,学习以自强!
onlinekb 发表于 2017-7-18 15:57:46 显示全部楼层
感谢楼主分享!
因分享而快乐,学习以自强!
zys91011 发表于 2017-7-24 10:07:05 显示全部楼层
希望可以学到东西啦啦啦
因分享而快乐,学习以自强!
blacksnow 发表于 2017-8-7 01:15:42 显示全部楼层
很有帮助
学习
因分享而快乐,学习以自强!
lavender_HSEP 发表于 2018-3-8 01:41:40 显示全部楼层
学习中,很棒
因分享而快乐,学习以自强!
废狗 发表于 2018-7-21 23:35:44 显示全部楼层
github上链接不知道还有效没
因分享而快乐,学习以自强!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

VR/AR版块|Unity3d|Unreal4|新手报道|小黑屋|站点地图|沪ICP备14023207号-9|【泰斗社区】-专注互联网游戏和应用的开发者平台 ( 浙ICP 备 13006852号-15 )|网站地图

© 2001-2013 Comsenz Inc.  Powered by Discuz! X3.4

1
QQ