u3d_rpg游戏开发之物品管理(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u3d_20171030/article/details/78608425

1. 创建三个脚本

 第一个是挂在物品栏上的,用来管理背包格子的,我这里取名为:Inventory
 第二个是挂在格子上的脚本,可以管理具体的格子,比如格子里的图片显示,不同的物品就显示不同的图片,以及一种物品的数量等等,取名为InventoryItemGrid
 第三个是挂在物品上的脚本,主要实现物品的拖拽功能,鼠标可以拖拽物品移动到不同的格子上InventoryItem

2. 先实现第三个脚本的一部分

 就是拖拽功能.这里用的是ugui.所以要实现拖拽就要让InventoryItem继承至MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler并且实现相应的接口
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.UI;
using UnityEngine.EventSystems;
//物品脚本,控制物品的拖拽功能
public class InventoryItem : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler {

    /// <summary>
    /// 实现接口的OnBeginDrag方法,处理开始拖拽时要做的事情
    /// </summary>
    /// <param name="eventData"></param>
    public void OnBeginDrag(PointerEventData eventData)
    {
        SetDraggedPosition(eventData);
    }

    /// <summary>
    /// 实现接口的OnDrag方法,处理拖动中要做的事情
    /// </summary>
    /// <param name="eventData"></param>

    public void OnDrag(PointerEventData eventData)
    {
        SetDraggedPosition(eventData);
    }

    /// <summary>
    /// 实现接口的OnEndDrag方法,处理结束时的方法
    /// </summary>
    /// <param name="eventData"></param>
    public void OnEndDrag(PointerEventData eventData)
    {
        SetDraggedPosition(eventData);
    }

    /// <summary>  
    /// set position of the dragged game object  
    /// </summary>  
    /// <param name="eventData"></param>  
    private void SetDraggedPosition(PointerEventData eventData)
    {
        var rt = gameObject.GetComponent<RectTransform>();

        // 将指针位于ui上的点转换为世界坐标点
        //如果如果指针在ui上则返回true
        //out worldpoint,out一个世界坐标点
        Vector3 globalMousePos;
        if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, eventData.position, eventData.pressEventCamera, out globalMousePos))
        {
            rt.position = globalMousePos;
        }
    }
}

有了这个脚本的ui就能拖动了

3. 接下来写物品栏的脚本

 也就是上面提到的第一个脚本,首先将Inventory做成单例模式
public static Inventory _inventory;//做成单例模式
 我们的物品栏里面肯定有很多个格子,而每个格子只放一个物品,如下图

图片来源于siki老师的黑暗之光

    public List<InventoryItemGrid> itemGridList = new List<InventoryItemGrid>();//用来管理所有的格子

然后在u3d中把所有的格子添加到链表即可,之后就可以遍历链表来做到检查背包所有物品之类的功能
所有物品都有一个唯一的id,这也能作为计算机辨认物品的标识,在之前那一篇关于字典的使用就是本文的前言.
当我们拾取一个物品,即可获取这个物品的id,然后从字典中获取这个物品的所有信息,再把这件物品添加到格子中.
从字典中获取到的信息就包含这个物品相对应的图片的名字,方便我们找到相应的图片,以显示在格子中.
而格子会有专门的一个Image的组件来负责显示图片,添加了不同物品就显示相应的图片.
所以我在这里创建了一个Getid()的方法,需要一个int参数,这个参数为捡起物品的id

public void GetId(int id)
    {
        InventoryItemGrid grid = null;//用来存储物品
        //遍历物品栏中的物品,是否有id为id物品,如果有就赋值给grid
        foreach (InventoryItemGrid temp in itemGridList)
        {
            if (temp.id == id)
            {
                grid = temp; break;
            }
        }
        //如果物品栏中有该物品执行PlusNumber();使物品加一
        if (grid != null)
        {
            grid.PlusNumber();
        }
        else
        {
            //找到id为0也就是空的格子赋值给grid,如果格子满了,就放不下,即grid依然为空
            foreach (InventoryItemGrid temp in itemGridList)
            {
                if (temp.id == 0)
                {
                    myImage = temp.imgae;
                    temp.id = id;
                    grid = temp;
                    break;
                }
            }
            //如果grid不为空,就存放并更新图片
            if (grid != null)
            {
                SetId(id);
            }
        }
    }

注意:因为捡起物品时,有不同情况,比如,背包已经有了该物品,我们只需要让该物品数量加一即可,如果背包没有该物品,才去创建一个这种物品,然后数量就为1 ,所以我们在格子的脚本中写一个让物品加1的方法PlusNumber()
格子中的脚本有一个名为id的public变量,如果背包是空的,它的id就为0,否则就是格子里放的物品的id
so,思路清晰了,就可以给出整个脚本了

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.UI;

//背包栏上的脚本,用来管理背包内容
public class Inventory : MonoBehaviour {


    public static Inventory _inventory;//做成单例模式
    public List<InventoryItemGrid> itemGridList = new List<InventoryItemGrid>();//用来管理所有的格子
    public Text coinNumberText;//游戏界面中的金币数量显示



    private int coinCoent = 1000;//金币数量,设置成私有保证安全性




    void Update () {
        if (Input.GetKeyDown(KeyCode.X))
        {
            GetId(Random.Range(1001, 1004));
        }
    }

    /// <summary>
    /// 根据id拾取到相应的物品,并且添加到物品栏里
    /// 处理物品拾取物品的功能
    /// </summary>
    /// <param name="id"></param>
    public void GetId(int id)
    {
        InventoryItemGrid grid = null;//用来存储物品
        //遍历物品栏中的物品,是否有id为id物品,如果有就赋值给grid
        foreach (InventoryItemGrid temp in itemGridList)
        {
            if (temp.id == id)
            {
                grid = temp; break;
            }
        }
        //如果物品栏中有该物品执行PlusNumber();使物品加一
        if (grid != null)
        {
            grid.PlusNumber();
        }
        else//物品栏中没有该物品
        {
            //找到id为0也就是空的格子赋值给grid,如果格子满了,就放不下,即grid依然为空
            foreach (InventoryItemGrid temp in itemGridList)
            {
                if (temp.id == 0)
                {
                    //myImage = temp.imgae;
                    //temp.id = id;
                    grid = temp;
                    break;
                }
            }
            //如果grid不为空,就存放并更新图片
            if (grid != null)
            {
                grid.SetId(id);
            }
        }
    }
}

4. 最后写格子的脚本:InventoryItemGrid

这个脚本写出来,把所有的东西串联起来,思路就会清晰很多了.根据上面提到的,加上没有提到的,格子的脚本应该有的值有     
    public int id = 0;//表示格子放置的是哪个物品,0表示为空
    public Image imgae;//用来储存需要改变图片的image



    private int num = 0;//表示格子里的物品有多少个
    private Text text;//获取text组件,该组件用于显示num
    private ObjectInfo info=null;//格子中储存的物品



    void Start()
    {
        text = GetComponentInChildren<Text>();
        imgae = this.GetComponent<Image>();
    }

直接上整体代码,这边注释已经够看的了

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.UI;
using UnityEngine.EventSystems;
//方格脚本,用来处理方格物品功能
public class InventoryItemGrid : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler
{
    public int id = 0;//表示格子放置的是哪个物品,0表示为空
    public Image imgae;//用来储存需要改变图片的image



    private int num = 0;//表示格子里的物品有多少个
    private Text text;//获取text组件,该组件用于显示num
    private ObjectInfo info=null;//格子中储存的物品



    void Start()
    {
        text = GetComponentInChildren<Text>();
        imgae = this.GetComponent<Image>();
    }
    void IPointerEnterHandler.OnPointerEnter(PointerEventData eventData)
    {

    }

    void IPointerExitHandler.OnPointerExit(PointerEventData eventData)
    {

    }
    /// <summary>
    ///根据id储存格子中的物品并更新格子显示
    /// </summary>
    /// <param name="id">物品id</param>
    /// <param name="num">物品数量</param>
    public void SetId(int id,int num=1)
    {
        this.id = id;
        info = ObjectsInfo._instance.GetObjectInfoById(id);//从字典获取物品信息
        SetIconName("Icon/" + info.icon_name);//显示相应的图片
        this.num = num;//显示物品的数量
        text.gameObject.SetActive(true);
        text.text = num.ToString();//将物品的数量赋值给text来显示
    }
    /// <summary>
    /// 根据图片名字使格子显示不同图片
    /// </summary>
    /// <param name="icon_name">图片路径</param>
    private void SetIconName(string icon_name)
    {
        imgae.sprite = Resources.Load(icon_name, typeof(Sprite)) as Sprite;
    }
    /// <summary>
    /// 清空格子存储的物品信息
    /// </summary>
    public void ClearInfo()
    {
        id = 0;
        info = null;
        num = 0;
        text.gameObject.SetActive(false);
        text.text = "0";
    }
    /// <summary>
    /// 增加物品栏中的物品数量
    /// </summary>
    /// <param name="num">增加的数量</param>
    public void PlusNumber(int num = 1)
    {
        this.num += num;
        text.text = this.num.ToString();
    }
}

猜你喜欢

转载自blog.csdn.net/u3d_20171030/article/details/78608425