版权声明:本文为博主原创文章,未经博主允许不得转载。 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;//做成单例模式
我们的物品栏里面肯定有很多个格子,而每个格子只放一个物品,如下图
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();
}
}