Tools
FileTools
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Text;
public static class FileTools  {/// <summary>/// 读取指定路径的json文件/// </summary>/// <param name="path"></param>/// <returns></returns>public static string ReadJson(string path){if (!File.Exists(path)){return "";}string json = "";StreamReader sr = new StreamReader(path, Encoding.UTF8);try{json = sr.ReadToEnd();}catch (System.Exception e){Debug.Log(e.ToString());}sr.Close();return json;}/// <summary>/// 把json写入指定的文件a/// </summary>/// <param name="path"></param>/// <param name="json"></param>public static void WriteJson(string path, string json){if (!File.Exists(path)){FileStream fs = File.Create(path);fs.Close();}StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8);try{sw.Write(json);}catch (System.Exception e){Debug.Log(e.ToString());}sw.Close();}}

SaveManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SaveManager
{#region 单例private static SaveManager instance;public static SaveManager Instance{get {if (null == instance){instance = new SaveManager();}return instance;}}private SaveManager() { }#endregion/// <summary>/// 初始化数据/// </summary>public void InitData(){//初始化人物的数据string playerJson = FileTools.ReadJson(Application.streamingAssetsPath + "/Json/PlayerData.txt");if (playerJson == ""){PlayerData.SetInstance(null);}else{PlayerData.SetInstance(JsonUtility.FromJson<PlayerData>(playerJson));         }//Debug.Log(PlayerData.Instance.Atk);
        PlayerData.Instance.Init();//初始化背包数据string bagJson = FileTools.ReadJson(Application.streamingAssetsPath + "/Json/Bag.txt");if (bagJson == ""){BagData.SetInstance(null);}else{BagData.SetInstance(JsonUtility.FromJson<BagData>(bagJson));}//for (int i = 0; i < BagData.Instance.Items.Count; i++)//{//    Debug.Log("");//}BagData.Instance.UpdateCurrentCapacity();//更新一次负重
    }/// <summary>/// 保存数据/// </summary>public void SaveData(){//保存玩家的数据string playerJson = JsonUtility.ToJson(PlayerData.Instance, true);FileTools.WriteJson(Application.streamingAssetsPath + "/Json/PlayerData.txt", playerJson);//保存背包的数据string bagJson = JsonUtility.ToJson(BagData.Instance, true);FileTools.WriteJson(Application.streamingAssetsPath + "/Json/Bag.txt", bagJson);}
}

GameManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour {// Use this for initializationvoid Awake () {DontDestroyOnLoad(gameObject);SaveManager.Instance.InitData();}// Update is called once per framevoid OnDestroy () {SaveManager.Instance.SaveData();}
}

Json
PlayerData
{"items": [{"id": 2,"itemName": "肚兜","iconName": "FaShi_XiongJia_5","atk": 0.0,"def": 999.0,"thump": 0.0,"hp": 1000.0,"mp": 2000.0,"anger": 0.0,"weight": 1.0,"type": 2},{"id": 1,"itemName": "大贱","iconName": "DaJian_08","atk": 999.0,"def": 0.0,"thump": 0.9900000095367432,"hp": 100.0,"mp": 100.0,"anger": 500.0,"weight": 2.0,"type": 0}],"atk": 20.0,"def": 20.0,"thump": 0.5,"hp": 100.0,"mp": 100.0,"anger": 0.0
}

Bag

{"items": [{"id": 3,"itemName": "肚兜","iconName": "FaShi_XiongJia_4","atk": 0.0,"def": 999.0,"thump": 0.0,"hp": 1000.0,"mp": 2000.0,"anger": 0.0,"weight": 1.0,"type": 2},{"id": 4,"itemName": "大贱","iconName": "DaJian_08","atk": 999.0,"def": 0.0,"thump": 0.9900000095367432,"hp": 100.0,"mp": 100.0,"anger": 500.0,"weight": 2.0,"type": 0},{"id": 5,"itemName": "肚兜","iconName": "FaShi_XiongJia_5","atk": 0.0,"def": 999.0,"thump": 0.0,"hp": 1000.0,"mp": 2000.0,"anger": 0.0,"weight": 1.0,"type": 2},{"id": 6,"itemName": "肚兜","iconName": "FaShi_XiongJia_4","atk": 0.0,"def": 999.0,"thump": 0.0,"hp": 1000.0,"mp": 2000.0,"anger": 0.0,"weight": 1.0,"type": 2},{"id": 2,"itemName": "肚兜","iconName": "FaShi_XiongJia_5","atk": 0.0,"def": 999.0,"thump": 0.0,"hp": 1000.0,"mp": 2000.0,"anger": 0.0,"weight": 1.0,"type": 2},{"id": 1,"itemName": "大贱","iconName": "DaJian_08","atk": 999.0,"def": 0.0,"thump": 0.9900000095367432,"hp": 100.0,"mp": 100.0,"anger": 500.0,"weight": 2.0,"type": 0},{"id": 7,"itemName": "肚兜","iconName": "FaShi_XiongJia_4","atk": 0.0,"def": 999.0,"thump": 0.0,"hp": 1000.0,"mp": 2000.0,"anger": 0.0,"weight": 1.0,"type": 2}],"maxCapacity": 100.0
}

Model
ItemData
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 该类用于存储装备的基本属性
/// </summary>
[System.Serializable]//因为对于已有的数据是从文件中来的,所以需要加序列化标识
public class ItemData
{#region 私有变量[SerializeField]private int id;//作为物品的唯一标识
    [SerializeField]private string itemName;//物品的名字
    [SerializeField]private string iconName;//物品显示图片的名字
    [SerializeField]private float atk;//攻击力加成
    [SerializeField]private float def;//防御力加成
    [SerializeField]private float thump;//暴击率加成
    [SerializeField]private float hp;//血量加成
    [SerializeField]private float mp;//加成
    [SerializeField]private float anger;//怒气加成
    [SerializeField]private float weight;//重量
    [SerializeField]private ItemType type;//物品的类型#endregion#region 属性public int Id{get{return id;}}public string ItemName{get{return itemName;}}public string IconName{get{return iconName;}}public float Atk{get{return atk;}}public float Def{get{return def;}}public float Thump{get{return thump;}}public float Hp{get{return hp;}}public float Mp{get{return mp;}}public float Anger{get{return anger;}}public float Weight{get{return weight;}}public ItemType Type{get{return type;}}#endregion#region 构造函数public ItemData() { }public ItemData(int id, string itemName, string iconName, float atk,float def, float thump, float hp, float mp, float anger, float weight, ItemType type){this.id = id;this.itemName = itemName;this.iconName = iconName;this.atk = atk;this.def = def;this.thump = thump;this.hp = hp;this.mp = mp;this.anger = anger;this.weight = weight;this.type = type;}#endregionpublic static string GetTypeName(ItemType type){string typeName = "";switch (type){case ItemType.Weapon:typeName = "武器";break;case ItemType.Cap:typeName = "头盔";break;case ItemType.Armour:typeName = "铠甲";break;case ItemType.Belt:typeName = "腰带";break;case ItemType.Ring:typeName = "戒指";break;case ItemType.Headwear:typeName = "头饰";break;case ItemType.Necklace:typeName = "项链";break;case ItemType.Shoe:typeName = "靴子";break;}return typeName;}
}

ItemType

/// <summary>
/// 物品的类型, 装备栏能装备的类型
/// </summary>
public enum ItemType
{Weapon,//武器Cap,//头盔Armour,//铠甲Ring,//戒指Belt,//腰带Necklace,//项链Shoe,//鞋子Headwear,//头饰
}

PlayerData
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class PlayerData
{#region 单例private static PlayerData instance;//这个数据类的单例,从文件中反序列化来的public static PlayerData Instance{get {return instance;}}private PlayerData() { }/// <summary>/// 对单例进行赋值/// </summary>/// <param name="data"></param>public static void SetInstance(PlayerData data){if (null == data){instance = new PlayerData();}else{instance = data;}}#endregionpublic List<ItemData> items;//人物身上穿戴的装备#region 私有变量[SerializeField]private float atk;//基础攻击力
    [SerializeField]private float def;//基础防御力
    [SerializeField]private float thump;//基础暴击率
    [SerializeField]private float hp;//基础血量
    [SerializeField]private float mp;//基础魔法
    [SerializeField]private float anger;//基础怒气//装备的属性加成都是装备的装备计算出来的private float addAtk;//装备攻击力加成private float addDef;//
    private float addThump;//
    private float addHp;//
    private float addMp;//
    private float addAnger;//
    #endregion#region 事件//当数据发生改变时,通过该事件通知界面public event Action updateEvent;#endregion#region 属性public float Atk{get{return atk;}}public float Def{get{return def;}}public float Thump{get{return thump;}}public float Hp{get{return hp;}}public float Mp{get{return mp;}}public float Anger{get{return anger;}}public float AddAtk{get{return addAtk;}}public float AddDef{get{return addDef;}}public float AddThump{get{return addThump;}}public float AddHp{get{return addHp;}}public float AddMp{get{return addMp;}}public float AddAnger{get{return addAnger;}}#endregion#region 提供一些访问或删除装备的方法/// <summary>/// 通过装备的ID来访问装备/// </summary>/// <param name="id"></param>/// <returns></returns>public ItemData GetItem(int id){for (int i = 0; i < items.Count; i++){if (id == items[i].Id){return items[i];}}return null;}/// <summary>/// 通过装备的类型来访问装备/// </summary>/// <param name="type"></param>/// <returns></returns>public ItemData GetItem(ItemType type){for (int i = 0; i < items.Count; i++){if (type == items[i].Type){return items[i];}}return null;}/// <summary>/// 添加装备/// </summary>/// <param name="data"></param>public void AddItem(ItemData data){items.Add(data);//数据发生改变,装备的属性加成需要重新计算
        UpdateAdditionData();//数据发生变化,通知界面
        UpdatePanel();}/// <summary>/// 删除装备/// </summary>/// <param name="data"></param>public void RemoveItem(ItemData data){if (items.Contains(data)){items.Remove(data);//数据发生改变,装备的属性加成需要重新计算
            UpdateAdditionData();//数据发生变化,通知界面
            UpdatePanel();}}/// <summary>/// 通过ID删除装备/// </summary>/// <param name="id"></param>public void RemoveItem(int id){ItemData data = GetItem(id);RemoveItem(data);}/// <summary>/// 通过装备类型删除装备/// </summary>/// <param name="type"></param>public void RemoveItem(ItemType type){ItemData data = GetItem(type);RemoveItem(data);}#endregionpublic void Init(){UpdateAdditionData();}/// <summary>/// 计算装备的加成数据, 每次当数据发生改变的时候调用/// </summary>void UpdateAdditionData(){this.addAtk = 0;this.addDef = 0;this.addThump = 0;this.addHp = 0;this.addMp = 0;this.addAnger = 0;//把每一件装备的加成数据加给实际的数据for (int i = 0; i < items.Count; i++){this.addAtk += items[i].Atk;this.addDef += items[i].Def;this.addThump += items[i].Thump;this.addHp += items[i].Hp;this.addMp += items[i].Mp;this.addAnger += items[i].Anger;}}/// <summary>/// 通知界面改变/// </summary>void UpdatePanel(){if (updateEvent != null){updateEvent();}}
}

BagData

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class BagData
{#region 单例private static BagData instance;//从文件中反序列化来的public static BagData Instance{get {return instance;}}private BagData() { }public static void SetInstance(BagData data){if (data == null){instance = new BagData();instance.items = new List<ItemData>();}else{instance = data;}}#endregion#region 私有变量[SerializeField]private List<ItemData> items;//当前的所有的装备
    [SerializeField]private float maxCapacity;//最大容量, 从文件中读取进来的private float currentCapacity;//当前容量, 根据当前背包的装备计算出来的#endregion#region 事件public event Action updateEvent;//定义一个事件,当数据改变时,调用事件通知界面更新#endregion#region 属性public float MaxCapacity{get{return maxCapacity;}}public float CurrentCapacity{get{return currentCapacity;}}public List<ItemData> Items{get{return items;}}#endregion#region 提供一些操作背包装备的方法/// <summary>/// 使用ID访问背包中的装备/// </summary>/// <param name="id"></param>/// <returns></returns>public ItemData GetItem(int id){for (int i = 0; i < items.Count; i++){if (items[i].Id == id){return items[i];}}return null;}/// <summary>/// 添加装备/// </summary>/// <param name="id"></param>public void AddItem(ItemData data){items.Add(data);//每一次数据改变,当前负重都是需要重新计算的
        UpdateCurrentCapacity();//数据变了,通知界面
        UpdatePanel();}/// <summary>/// 删除装备/// </summary>/// <param name="data"></param>public void RemoveItem(ItemData data){//判断data是否在Items里if (items.Contains(data)){items.Remove(data);}UpdateCurrentCapacity();//数据变了,通知界面
        UpdatePanel();}/// <summary>/// 删除指定ID的装备/// </summary>/// <param name="id"></param>public void RemoveItem(int id){ItemData data = GetItem(id);if (data != null){RemoveItem(data);}}#endregionpublic void UpdateCurrentCapacity(){currentCapacity = 0;//把每一件装备的负重累加在一起,就是当前的负重for (int i = 0; i < items.Count; i++){currentCapacity += items[i].Weight;}}/// <summary>/// 通知界面更新/// </summary>void UpdatePanel(){if (updateEvent != null){updateEvent();}}public void ItemsSort(){items.Sort(ItemSort);//物品之间的顺序发生了改变, 通知界面更新
        UpdatePanel();}/// <summary>/// 物品的排序,以物品的类型排/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>int ItemSort(ItemData a, ItemData b){int tempA = (int)a.Type;int tempB = (int)b.Type;if (tempA < tempB){return -1;}else if (tempA > tempB){return 1;}else{return 0;}}
}

View
PlayerUI
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerUI : MonoBehaviour {private GridBase[] grids;//所有的装备栏//所有显示属性的Textprivate Text atkText;private Text defText;private Text thumpText;private Text hpText;private Text mpText;private Text angerText;void Awake () {//在子物体里获取所有的GridBase这个组件,返回的是一个数组grids = gameObject.GetComponentsInChildren<GridBase>();atkText = transform.Find("Message/AtkText").GetComponent<Text>();defText = transform.Find("Message/DefText").GetComponent<Text>();thumpText = transform.Find("Message/ThumpText").GetComponent<Text>();hpText = transform.Find("Message/HPText").GetComponent<Text>();mpText = transform.Find("Message/MPText").GetComponent<Text>();angerText = transform.Find("Message/AngerText").GetComponent<Text>();//ItemData data = new ItemData();//Debug.Log(JsonUtility.ToJson(data, true));
    }private void Start(){PlayerData.Instance.updateEvent += UpdatePanel;UpdatePanel();}private void OnDestroy(){PlayerData.Instance.updateEvent -= UpdatePanel;}/// <summary>/// 更新界面的方法/// </summary>void UpdatePanel(){//把人物身上装备的物品显示, 所有属性显示//先把所有的格子清空for (int i = 0; i < grids.Length; i++){grids[i].UpdateItem(-1, "");}//再把人物身上装备显示在对应的格子上for (int i = 0; i < grids.Length; i++){PlayerGridUI grid = grids[i] as PlayerGridUI;for (int j = 0; j < PlayerData.Instance.items.Count; j++){//当格子的装备与人物数据里的装备的类型是一致时,证明该装备应该放在这个格子上if (grid.gridType == PlayerData.Instance.items[j].Type){grid.UpdateItem(PlayerData.Instance.items[j].Id, PlayerData.Instance.items[j].IconName);}}}atkText.text = "攻击力:" + PlayerData.Instance.Atk + "<color=\"green\"> + "+ PlayerData.Instance.AddAtk + "</color>";defText.text = "防御力:" + PlayerData.Instance.Def + "<color=\"green\"> + "+ PlayerData.Instance.AddDef + "</color>";thumpText.text = "暴击率:" + PlayerData.Instance.Thump + "<color=\"green\"> + "+ PlayerData.Instance.AddThump + "</color>";hpText.text = "生命值:" + PlayerData.Instance.Hp + "<color=\"green\"> + "+ PlayerData.Instance.AddHp + "</color>";mpText.text = "魔法值:" + PlayerData.Instance.Mp + "<color=\"green\"> + "+ PlayerData.Instance.AddMp + "</color>";angerText.text = "怒气值:" + PlayerData.Instance.Anger + "<color=\"green\"> + "+ PlayerData.Instance.AddAnger + "</color>";}
}

BagUI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BagUI : MonoBehaviour {private GridBase[] grids;private Text weightText;private Text numText;private Button rightButton;private Button leftButton;private Button clearUpButton;private int currentNum;private int maxNum;//根据背包里物品数量与当前有多少个格子比较void Awake () {//获取所有的格子grids = gameObject.GetComponentsInChildren<GridBase>();weightText = transform.Find("CapacityText").GetComponent<Text>();numText = transform.Find("Num/Num/Text").GetComponent<Text>();rightButton = transform.Find("Num/RightButton").GetComponent<Button>();leftButton = transform.Find("Num/LeftButton").GetComponent<Button>();clearUpButton = transform.Find("ClearUpButton").GetComponent<Button>();//按钮注册事件
        rightButton.onClick.AddListener(RightClick);leftButton.onClick.AddListener(LeftClick);clearUpButton.onClick.AddListener(ClearUpClick);}private void Start(){BagData.Instance.updateEvent += UpdatePanel;currentNum = 1;//界面一开始,当前页是1
        UpdatePanel();}private void OnDestroy(){BagData.Instance.updateEvent -= UpdatePanel;}/// <summary>/// 更新界面/// </summary>void UpdatePanel(){//更新当前页数的物品, 更新当前页数, 更新当前的负重//计算当前的最大页数maxNum = (int)Mathf.Ceil(BagData.Instance.Items.Count / (float)grids.Length);numText.text = currentNum + "/" + maxNum;weightText.text = "负重:" + BagData.Instance.CurrentCapacity + "/" +BagData.Instance.MaxCapacity;//显示当前的页数的物品//根据当前页数,确定第一个位置应该排背包数据的里的第几个索引(起始索引)//模拟 格子: 20   当第一页是起始索引为0, 当第二页时起始索引为20int startIndex = (currentNum - 1) * grids.Length;//(当前页数 - 1) * 格子数量//把从起始索引开始,依次的把物品放在对应的格子上for (int i = 0; i < grids.Length; i++){//当i= 0时,证明是第一个格子,对应的物品索引 startIndex = startIndex + i//当i= 1时,证明是第二各格子,对应的物品索引 startIndex + 1 =  startIndex + i//....//当i = grids.Length - 1时, 最后一个格子, 对应的物品索引 startIndex + grids.Length - 1 =  startIndex + i//如果startIndex + i 超出了物品的数量, 证明这个格子没有物品//如果startIndex + i 没有超出物品的数量, 这个这个格子有物品if (startIndex + i >= BagData.Instance.Items.Count){//超出了物品的数量,该格子没有物品grids[i].UpdateItem(-1, "");}else{grids[i].UpdateItem(BagData.Instance.Items[startIndex + i].Id,BagData.Instance.Items[startIndex + i].IconName);}}}/// <summary>/// 翻页的右按钮/// </summary>void RightClick(){//Debug.Log("RightClick");//判断是当前页是是最后一页if (currentNum < maxNum){//不是最后一页currentNum++;UpdatePanel();//当前页数变了,需要更新一下界面的显示
        }}/// <summary>/// 翻页的左按钮/// </summary>void LeftClick(){//Debug.Log("LeftClick");//判断当前页数是不是第一页if (currentNum > 1){currentNum--;UpdatePanel();//当前页数变了,需要更新一下界面的显示
        }}/// <summary>/// 整理按钮/// </summary>void ClearUpClick(){Debug.Log("ClearUpClick");BagController.Instance.ClearUp();}
}

GridBase

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class GridBase : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler,IPointerClickHandler,IBeginDragHandler,IDragHandler,IEndDragHandler
{public int itemID = -1;// 规定-1  那么这个格子空的public Transform tempParent;//拖动时临时的父物体private Image image;//显示装备的图片private Vector2 outPos;//转换之后的坐标private Vector2 offset;//鼠标偏移量private RectTransform parentRT;protected void Init(){image = transform.Find("Item").GetComponent<Image>();parentRT = tempParent as RectTransform;}/// <summary>/// 更新自己本身的物品/// </summary>/// <param name="itemID"></param>/// <param name="iconName"></param>public virtual void UpdateItem(int itemID, string iconName){if (this.itemID == itemID && itemID >= 0){return;}this.itemID = itemID;if (itemID < 0)//没有物品
        {image.enabled = false;}else{image.enabled = true;if (image.sprite == null || image.sprite.name != iconName){Sprite sp = Resources.Load<Sprite>("Texture/Icon/" + iconName);image.sprite = sp;}}}#region 接口的虚方法//开始拖动的虚方法protected virtual void BeginDrag(PointerEventData eventData){if (itemID < 0) return;//Debug.Log("父类:BeginDrag");image.transform.parent = tempParent;if (RectTransformUtility.ScreenPointToLocalPointInRectangle(parentRT,eventData.position, eventData.enterEventCamera, out outPos)){offset = outPos - new Vector2(image.transform.localPosition.x, image.transform.localPosition.y);}}//拖动的虚方法protected virtual void Drag(PointerEventData eventData){if (itemID < 0) return;//Debug.Log("父类:Drag");if (RectTransformUtility.ScreenPointToLocalPointInRectangle(parentRT,eventData.position, eventData.enterEventCamera, out outPos)){image.transform.localPosition = outPos - offset;}}//拖动结束时的虚方法protected virtual void EndDrag(PointerEventData eventData){if (itemID < 0) return;//Debug.Log("父类:EndDrag");image.transform.parent = transform;image.transform.localPosition = Vector3.zero;}//点击的虚方法protected virtual void Click(PointerEventData eventData){//Debug.Log("父类:Click");
    }//进入的虚方法protected virtual void Enter(PointerEventData eventData){//Debug.Log("父类:Enter");//Debug.Log("显示信息");
    }//出去的虚方法protected virtual void Exit(PointerEventData eventData){//Debug.Log("父类:Exit");//Debug.Log("隐藏信息");
        TipsUI.Instance.HideTips();}#endregion#region 实现的接口public void OnBeginDrag(PointerEventData eventData){BeginDrag(eventData);}public void OnDrag(PointerEventData eventData){Drag(eventData);}public void OnEndDrag(PointerEventData eventData){EndDrag(eventData);}public void OnPointerClick(PointerEventData eventData){Click(eventData);}public void OnPointerEnter(PointerEventData eventData){Enter(eventData);}public void OnPointerExit(PointerEventData eventData){Exit(eventData);}#endregion
}

PlayerGridUI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class PlayerGridUI : GridBase {public ItemType gridType;private Text text;// Use this for initializationvoid Awake () {base.Init();text = transform.Find("Text").GetComponent<Text>();gameObject.tag = "PlayerGrid";text.text = ItemData.GetTypeName(gridType);}public override void UpdateItem(int itemID, string iconName){base.UpdateItem(itemID, iconName);if (itemID >= 0)//有装备
        {text.enabled = false;//有装备时,把装备栏的文字隐藏
        }else{text.enabled = true;}}protected override void BeginDrag(PointerEventData eventData){if (itemID < 0) return;base.BeginDrag(eventData);text.enabled = true;//开始拖动时,显示文字
    }protected override void Click(PointerEventData eventData){if (itemID < 0) return;if (eventData.button == PointerEventData.InputButton.Right){Debug.Log("卸下: " + itemID);BagController.Instance.DemountItem(itemID, CallBck);}}protected override void EndDrag(PointerEventData eventData){if (itemID < 0) return;base.EndDrag(eventData);text.enabled = false;//开始拖动时,显示文字if (eventData.pointerCurrentRaycast.gameObject != null &&eventData.pointerCurrentRaycast.gameObject.CompareTag("BagGrid")){Debug.Log("卸下装备");BagController.Instance.DemountItem(itemID, CallBck);}}protected override void Enter(PointerEventData eventData){//eventData.dragging 是否处于拖动状态, 鼠标按下,并且再移动if (eventData.dragging) return;TipsUI.Instance.ShowTips(itemID, TipsUI.ItemGridType.Player, transform.position);}void CallBck(bool isFinish, string message){//暂时测试使用if (isFinish){Debug.Log("完成了: " + message);}else{Debug.LogError(message);}}
}

BagGridUI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class BagGridUI : GridBase {void Awake () {base.Init();gameObject.tag = "BagGrid";}protected override void Click(PointerEventData eventData){if (itemID < 0) return;if (eventData.button == PointerEventData.InputButton.Right){Debug.Log("装备: " + itemID);BagController.Instance.EquipmentItem(itemID, BagData.Instance.GetItem(itemID).Type, CallBck);}}protected override void EndDrag(PointerEventData eventData){if (itemID < 0) return;base.EndDrag(eventData);if (eventData.pointerCurrentRaycast.gameObject == null)//当拖出背包区域时
        {Debug.Log("卖出物品");BagController.Instance.SellItem(itemID, CallBck);}else if(eventData.pointerCurrentRaycast.gameObject.CompareTag("PlayerGrid")){Debug.Log("装备物品");//获取到鼠标当前检测到的装备栏的类型PlayerGridUI grid = eventData.pointerCurrentRaycast.gameObject.GetComponent<PlayerGridUI>();BagController.Instance.EquipmentItem(itemID, grid.gridType, CallBck);}}protected override void Enter(PointerEventData eventData){//eventData.dragging 是否处于拖动状态, 鼠标按下,并且再移动if (eventData.dragging) return;TipsUI.Instance.ShowTips(itemID, TipsUI.ItemGridType.Bag, transform.position);}void CallBck(bool isFinish, string message){//暂时测试使用if (isFinish){Debug.Log("完成了: " + message);}else{Debug.LogError(message);}}
}

TipsUI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TipsUI : MonoBehaviour
{private Text nameText;private Text typeText;private Text atkText;private Text defText;private Text thumpText;private Text hpText;private Text mpText;private Text angerText;private Text weightText;private static TipsUI instance;public static TipsUI Instance{get{/*if (null == instance){instance = GameObject.Find("Tips").GetComponent<TipsUI>();}*/return instance;}}// Use this for initializationvoid Awake(){instance = this;nameText = transform.Find("NameText").GetComponent<Text>();typeText = transform.Find("TypeText").GetComponent<Text>();atkText = transform.Find("AtkText").GetComponent<Text>();defText = transform.Find("DefText").GetComponent<Text>();thumpText = transform.Find("ThumpText").GetComponent<Text>();hpText = transform.Find("HpText").GetComponent<Text>();mpText = transform.Find("MpText").GetComponent<Text>();angerText = transform.Find("AngerText").GetComponent<Text>();weightText = transform.Find("WeightText").GetComponent<Text>();}// Update is called once per framevoid Start(){gameObject.SetActive(false);}/// <summary>/// 显示物品信息,/// </summary>/// <param name="id">物品的id</param>/// <param name="type">物品在哪</param>/// <param name="position">物品的位置</param>public void ShowTips(int id, ItemGridType type, Vector3 position){ItemData data = null;if (type == ItemGridType.Bag){data = BagData.Instance.GetItem(id);}else if (type == ItemGridType.Player){data = PlayerData.Instance.GetItem(id);}if (data != null){gameObject.SetActive(true);nameText.text = "名字:" + data.ItemName;typeText.text = "类型:" + ItemData.GetTypeName(data.Type);atkText.text = "攻击力: +" + data.Atk.ToString();defText.text = "防御力: +" + data.Def.ToString();thumpText.text = "暴击率: +" + data.Thump.ToString();hpText.text = "生命值: +" + data.Hp.ToString();mpText.text = "魔法值: +" + data.Mp.ToString();angerText.text = "怒气值: +" + data.Anger.ToString();weightText.text = "负重:" + data.Weight.ToString();transform.position = position;Vector2 pivot;//鼠标偏右if (Input.mousePosition.x > Screen.width / 2f){pivot.x = 1;}else{pivot.x = 0;}//鼠标偏上if (Input.mousePosition.y > Screen.height / 2f){pivot.y = 1;}else{pivot.y = 0;}(transform as RectTransform).pivot = pivot;}}/// <summary>/// 隐藏属性显示栏/// </summary>public void HideTips(){gameObject.SetActive(false);}public enum ItemGridType{Bag,Player}
}

Controller
BagController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BagController
{#region 单例private static BagController instance;public static BagController Instance{get{if (instance == null){instance = new BagController();}return instance;}}private BagController() { }#endregion//回调信息//第一个参数,是是否完成, 第二个参数, 传递过去的消息public delegate void CallBack(bool isFinish, string message);#region 处理数据的方法/// <summary>/// 卖出指定的ID的物品, 规定只能从背包卖/// 第二个参数是:当完成或者未完成时,回调调用自己的View中的方法。/// </summary>/// <param name="id"></param>public void SellItem(int id, CallBack callback){//通过ID从背包中找到物品ItemData data = BagData.Instance.GetItem(id);//如果data是null, 背包中没有这个物品,id有问题if (data == null){//通知调用这个方法的View 你的ID是有问题的吧。//Debug.LogError("通知调用这个方法的View 你的ID是有问题的吧。");if (callback != null){callback(false, "ID有问题!");}}else{//删除物品
            BagData.Instance.RemoveItem(data);if (callback != null){callback(true, "卖出成功");}}}/// <summary>/// 装备物品/// </summary>/// 参数1: 要装备的物品的ID/// 参数2: 要装备的位置/// 参数3: View的回调函数(通知View的成功了还是失败)public void EquipmentItem(int id, ItemType gridType, CallBack callback){//判断ID是否存在ItemData bagItem = BagData.Instance.GetItem(id);if (bagItem == null){//背包里没有这个ID的物品if (callback != null){callback(false, "背包里没有该ID的物品");}}else{//如果背包有这个物品,//判断该装备类型和你要装备的格子类型是否一致if (bagItem.Type == gridType)//装备类型与格子类型一致,可以装备
            {//1. 装备栏有物品, 替换//2. 装备栏没有物品, 直接装备//首先判断装备栏是否有物品ItemData playerItem = PlayerData.Instance.GetItem(gridType);if (playerItem == null){//证明该格子上没有装备//先把该装备从背包数据里删除
                    BagData.Instance.RemoveItem(bagItem);//再把物品添加到人物数据里
                    PlayerData.Instance.AddItem(bagItem);}else{//证明该格子上有装备//先把人物身上的装备先删除
                    PlayerData.Instance.RemoveItem(playerItem);//再把背包里的装备删除
                    BagData.Instance.RemoveItem(bagItem);//把人物身上的装备添加到背包里
                    BagData.Instance.AddItem(playerItem);//把背包里的装备添加到人物身上
                    PlayerData.Instance.AddItem(bagItem);}if (callback != null){callback(true, "装备成功");}}else{if (callback != null){callback(false, "请把装备装到正确的位置");}}}}/// <summary>/// 卸下指定的id的装备,数据一定在playerData里/// </summary>/// <param name="id"></param>/// <param name="callback"></param>public void DemountItem(int id, CallBack callback){//判断playerData里是否有这个id的装备ItemData data = PlayerData.Instance.GetItem(id);if (data == null)//空的时候,身上没有这个id的物品
        {if (callback != null){callback(false, "人物身上没有该ID的物品");}}else{//先把该装备从人物身上删除
            PlayerData.Instance.RemoveItem(data);//再把该装备添加到背包数据里去
            BagData.Instance.AddItem(data);//通知界面成功if (callback != null){callback(true, "成功卸载装备");}}}/// <summary>/// 整理背包的方法/// </summary>public void ClearUp(){BagData.Instance.ItemsSort();}#endregion
}

LessonListSort

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LessonListSort : MonoBehaviour {List<int> listInt = new List<int>() { 1, 9, 4, 6, 0 };List<Obj> listObj = new List<Obj>() { new Obj(1, "小明"), new Obj(2, "小红") };// Use this for initializationvoid Start () {listInt.Sort(ListIntSort);for (int i = 0; i < listInt.Count; i++){Debug.Log(listInt[i]);}listObj.Sort(ListObjSort);for (int i = 0; i < listObj.Count; i++){Debug.Log(listObj[i].name);}}// Update is called once per framevoid Update () {}int ListIntSort(int a, int b){if (a < b){return -1;}else if (a > b){return 1;}else{return 0;}}public class Obj{public int id;public string name;public Obj(int id, string name){this.id = id;this.name = name;     }}int ListObjSort(Obj a, Obj b){if (a.id < b.id){return 1;}else if (a.id > b.id){return -1;}else{return 0;}}
}

改格子的枚举

假ID报错

无法再次装备的问题:取消格子里图片和文本的射线检测

整理功能,即列表排序

数值的排序
类对象的排序
List的自定义排序
List.sort(有int返回值,有两个参数List存储类型的参数)
对于这个方法
Int Sort (T a, T b)
如果返回值是-1,a排在b前
如果返回值是1,b排在a前
如果返回值是,a,b的权重是一致的
枚举转Int,也可比较大
关闭射线检测

转载于:https://www.cnblogs.com/cnwuchao/p/10363686.html

Unity3D学习笔记(二十七):MVC框架下的背包系统(2)相关推荐

  1. uniapp 学习笔记二十七 购物车总价计算及弹窗交互逻辑完善

    uniapp 学习笔记二十七 购物车总价计算及弹窗交互逻辑完善 uniapp 学习笔记二十七 购物车总价计算及弹窗交互逻辑完善 cart.vue <template><view> ...

  2. Mr.J-- jQuery学习笔记(二十七)--DOM操作方法(删除获取文本)

    清除 <body> <button>调用remove</button> <div>我是div<p>我是段落</p> </d ...

  3. 大数据学习笔记二:Ubuntu/Debian 下安装大数据框架Hadoop

    文章目录 安装Java 为Hadoop创建用户 安装Hadoop 配置Hadoop 配置环境变量 设置配置文件 格式化namenode 启动hadoop集群 访问hadoop集群 大数据学习系列文章: ...

  4. Qt学习笔记(二十七):QLabel 的常用方法

    一.QLabel 的构造函数: 1.QLabel(QWidget * parent = 0, Qt::WindowFlags f = 0):创建 QLabel 控件时,指定其父对象,并设置其窗口属性( ...

  5. Flask学习笔记(二):基于Flask框架上传图片到服务器端并原名保存

    文章目录 1.什么是Flask 2.通过Flask上传图片到服务器端(以原名保存) 1.什么是Flask Flask是一个基于python开发并依赖于 jinja2 模板和 werkzeug WSGI ...

  6. C++语法学习笔记二十七: 引用折叠,转发、完美转发,forward

    实例代码 // 引用折叠,转发.完美转发,forward#include <iostream>using namespace std;template<typename T> ...

  7. python学习笔记(二十七) -- 常用内建模块(二) Base64、MD5、SHA1、hmac

    目录 base64 hashlib MD5 SHA1 hmac base64 原理 base64就是对二进制数据进行编码,比如我有6字节的二进制数据,然后每3个字节分为一组,也就是一组有3*8 = 2 ...

  8. Unity3D学习笔记(十七):IK动画、粒子系统和塔防

    新动画系统: 反向动力学动画(IK功能): 魔兽世界(头部动画),神秘海域(手部动画),人类一败涂地(手部动画) 如何启用(调整) 1.必须是新动画系统Animator 设置头.手.肘的目标点 2.动 ...

  9. 马哥学习笔记二十七——IO复用

    I/O动作模式 阻塞 非阻塞 I/O复用 信号驱动 异步 转载于:https://www.cnblogs.com/wangyongbin/p/3817353.html

  10. Java学习笔记 (二十七) 使用NIO写文件

    使用Channel 写数据 代码如下: public static void main(String []args){try(FileOutputStream fos=new FileOutputSt ...

最新文章

  1. WordPress Editorial Calendar插件权限安全绕过漏洞
  2. IntelliJ IDEA 18 周岁,吐血推进珍藏已久的必装插件
  3. 3级联动 ajax java_java+ajax(三级连动下拉框)
  4. mysql查询 百万_MySQL百万级数据分页查询优化
  5. JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecut
  6. log4j.xml的实用例子
  7. java interface作用是什么_关于Java反射原理:
  8. 百度竞价后台操作技巧
  9. codeigniter mysql -1_mysql-Codeigniter-多个数据库连接
  10. ios 网速监控_iOS 监测网络状态
  11. 集成学习——bagging原理及分析
  12. docker实践-oxidized网络设备自动备份部署
  13. 夏斌:半年宏观调控思路的建议
  14. 程序员的算法趣题Q57: 最快的联络网
  15. 面向对象设计模式之备忘录模式
  16. 新东方雅思词汇---7.4、cap
  17. 苹果macos打开允许未知来源
  18. Springboot实现语音听写转文字功能
  19. 算法优秀书籍汇总---学习路线图
  20. CSS画三角形、箭头

热门文章

  1. [1] 图像预处理----图像灰度化处理
  2. file 图片上传 java_Java MultipartFile 上传文件/上传图片 亲测
  3. 二叉树遍历——深度优先遍历、广度优先遍历
  4. pandas merge融合
  5. mysql 按字段排序
  6. Caffe傻瓜系列(1):数据层及参数
  7. 基于微博数据的人物性格分类系统
  8. python之range与xrange使用区别
  9. Python3的opencv环境搭建简易教程
  10. linux进程状态a,Linux进程状态标识符含义