5-9 Complete Items Tooltip
今天要來完善Tooltip的功能,之前的章節中我們僅完成滑鼠移動到物品上,會顯示該物品的名稱,現在則是要加入其他詳細資訊。首先,先提供新的JSON格式:
Items.json:
大家應該會發現我有修改了下JSON的規格,新增了三種不同的List分為ConsumableEntityList、EquipmentEntityList、MaterialEntityList。然後在Item.cs中修改了部分程式碼,解析這三種新的List。
在InventorySystem.cs中的GetItemByID方法也略為麻煩,必須要修改成三個foreach迴圈,用來尋訪上述新增的三個新的List。
另外,我在GetToolTipText方法中,使用<color>標籤來標示不同功能的文字,這是Text一個很方便的功能,大家也可以從Unity官方教學了解一下Text有哪些可使用的標籤。
https://docs.unity3d.com/Manual/StyledText.html
接下來,提供本次修改後的完整程式碼給大家。另外,我在GetToolTipText方法中使用StringBuilder來串接動態字串,效率會比較高,大家可以參考這篇文章:
[C#]字串組合的時間效能大比拚(+=、Str.Format、StringBuilder.Append、SB.AppendFormat)
https://dotblogs.com.tw/doraemon0527/2011/01/23/20965
InventorySystem.cs:
Item.cs:
Consumable.cs:
Equipment.cs:
Materials.cs:
最後,來執行遊戲看看結果吧!把滑鼠移動到裝備上後會顯示裝備資訊,根據不同的等級的武器名稱的顏色也不同,數字部分則是用黃色來標記。
這是合成材料的標記。
這是消耗品的標記,這樣就完成了完整的Tooltip功能嘍!
Items.json:
{"ConsumableEntityList":[ { "ID":1, "Name":"血量瓶", "ItemTypeString":"Consumable", "ItemQualityString":"Common", "Description":"+ 25 HP", "Capacity":10, "BuyPrice":10, "SellPrice":10, "Sprite":"Sprites/Items/hp", "HP":10, "MP":0 }, { "ID":2, "Name":"能量瓶", "ItemTypeString":"Consumable", "ItemQualityString":"Common", "Description":"+ 50 MP", "Capacity":10, "BuyPrice":10, "SellPrice":10, "Sprite":"Sprites/Items/mp", "HP":0, "MP":10 } ], "EquipmentEntityList":[ { "ID":3, "Name":"胸甲", "ItemTypeString":"Equipment", "ItemQualityString":"Rare", "Description":"+ 50 DEF", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/armor", "Strength":10, "Intellect":0, "Agility":10, "Stamina":50, "EquipmentTypeString":"Armor" }, { "ID":4, "Name":"皮腰帶", "ItemTypeString":"Equipment", "ItemQualityString":"Epic", "Description":"+ 20 AGI +50 STA", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/belts", "Strength":0, "Intellect":0, "Agility":20, "Stamina":50, "EquipmentTypeString":"Belt" }, { "ID":5, "Name":"靴子", "ItemTypeString":"Equipment", "ItemQualityString":"Legendary", "Description":"+ 50 AGI", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/boots", "Strength":0, "Intellect":0, "Agility":50, "Stamina":0, "EquipmentTypeString":"Boots" }, { "ID":6, "Name":"護腕", "ItemTypeString":"Equipment", "ItemQualityString":"Rare", "Description":"+ 50 STA", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/bracers", "Strength":0, "Intellect":0, "Agility":0, "Stamina":50, "EquipmentTypeString":"Bracer" }, { "ID":7, "Name":"手套", "ItemTypeString":"Equipment", "ItemQualityString":"Common", "Description":"+20 STR + 50 STA", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/gloves", "Strength":20, "Intellect":0, "Agility":0, "Stamina":50, "EquipmentTypeString":"OffHand" }, { "ID":8, "Name":"頭盔", "ItemTypeString":"Equipment", "ItemQualityString":"Artifact", "Description":"+20 STR + 100 STA", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/helmets", "Strength":20, "Intellect":0, "Agility":0, "Stamina":100, "EquipmentTypeString":"Head" }, { "ID":9, "Name":"項鍊", "ItemTypeString":"Equipment", "ItemQualityString":"Rare", "Description":"+20 STR + 50 STA", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/necklace", "Strength":20, "Intellect":0, "Agility":0, "Stamina":50, "EquipmentTypeString":"Neck" }, { "ID":10, "Name":"戒指", "ItemTypeString":"Equipment", "ItemQualityString":"Common", "Description":"+30 INT", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/rings", "Strength":0, "Intellect":30, "Agility":0, "Stamina":0, "EquipmentTypeString":"Ring" }, { "ID":11, "Name":"褲子", "ItemTypeString":"Equipment", "ItemQualityString":"Uncommon", "Description":"+50 STA", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/pants", "Strength":0, "Intellect":0, "Agility":0, "Stamina":50, "EquipmentTypeString":"Leg" }, { "ID":12, "Name":"護肩", "ItemTypeString":"Equipment", "ItemQualityString":"Legendary", "Description":"+50 STA", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/shoulders", "Strength":0, "Intellect":0, "Agility":0, "Stamina":50, "EquipmentTypeString":"Shoulder" }, { "ID":13, "Name":"斧子", "ItemTypeString":"Weapon", "ItemQualityString":"Rare", "Description":"+50 STR", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/axe", "Damage":50, "WeaponTypeString":"MainHand" }, { "ID":14, "Name":"劍", "ItemTypeString":"Weapon", "ItemQualityString":"Rare", "Description":"+60 STR", "Capacity":1, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/sword", "Damage":60, "WeaponTypeString":"OffHand" } ], "MaterialEntityList":[ { "ID":15, "Name":"鍛造秘笈", "ItemTypeString":"Material", "ItemQualityString":"Artifact", "Description":"合成一把斧子的鍛造秘笈", "Capacity":10, "BuyPrice":100, "SellPrice":10, "Sprite":"Sprites/Items/book" }, { "ID":16, "Name":"鍛造秘笈", "ItemTypeString":"Material", "ItemQualityString":"Artifact", "Description":"合成一個頭盔的鍛造秘笈", "Capacity":10, "BuyPrice":100, "SellPrice":10, "Sprite":"Sprites/Items/scroll" }, { "ID":17, "Name":"鐵塊", "ItemTypeString":"Material", "ItemQualityString":"Rare", "Description":"合成裝備使用的鐵塊", "Capacity":100, "BuyPrice":20, "SellPrice":10, "Sprite":"Sprites/Items/ingots" } ]}
大家應該會發現我有修改了下JSON的規格,新增了三種不同的List分為ConsumableEntityList、EquipmentEntityList、MaterialEntityList。然後在Item.cs中修改了部分程式碼,解析這三種新的List。
在InventorySystem.cs中的GetItemByID方法也略為麻煩,必須要修改成三個foreach迴圈,用來尋訪上述新增的三個新的List。
另外,我在GetToolTipText方法中,使用<color>標籤來標示不同功能的文字,這是Text一個很方便的功能,大家也可以從Unity官方教學了解一下Text有哪些可使用的標籤。
https://docs.unity3d.com/Manual/StyledText.html
接下來,提供本次修改後的完整程式碼給大家。另外,我在GetToolTipText方法中使用StringBuilder來串接動態字串,效率會比較高,大家可以參考這篇文章:
[C#]字串組合的時間效能大比拚(+=、Str.Format、StringBuilder.Append、SB.AppendFormat)
https://dotblogs.com.tw/doraemon0527/2011/01/23/20965
InventorySystem.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Assertions; using UnityEngine.UI; namespace RPG.Inventory{ public class InventorySystem : MonoBehaviour { [SerializeField] ToolTip toolTip; ItemList itemList; Slot[] slotList; void Start () { ParseItemsJson (); slotList = GetComponentsInChildren(); // 測試程式碼,手動生成物品 StoreItem (1); StoreItem (2); StoreItem (1); StoreItem (3); StoreItem (4); StoreItem (5); StoreItem (6); StoreItem (7); StoreItem (8); StoreItem (9); StoreItem (10); StoreItem (11); StoreItem (12); StoreItem (7); StoreItem (8); StoreItem (9); StoreItem (13); StoreItem (14); StoreItem (15); StoreItem (16); StoreItem (17); } public void ShowToolTip(string content){ toolTip.Show (content); } public void HideToolTip(){ toolTip.Hide (); } public bool StoreItem(int id){ Item item = GetItemByID (id); return StoreItem (item); } public bool StoreItem(Item item){ if (item == null) { return false; } // 若物品的儲存容量為1,則將該物品直接放進空的Slot if (item.Capacity == 1) { return StoreItemInEmptySlot (item); } // 將相同的Item放在同一個Slot return StoreItemInSameSlot(item); } private bool StoreItemInSameSlot(Item item){ foreach (Slot slot in slotList) { if (slot.transform.childCount >= 1 && slot.GetItemID () == item.ID && slot.IsFilled () == false) { // 將新Item與同一個Item放在一起 slot.StoreItem (item); return true; } } // 若背包內不存在相同的Item,則放進空的Slot return StoreItemInEmptySlot (item); } private bool StoreItemInEmptySlot(Item item){ foreach (Slot slot in slotList) { if (slot.transform.childCount == 0) { // 將Item存進該Slot slot.StoreItem (item); return true; } } Debug.LogError ("No Empty Slot."); return false; } private Item GetItemByID(int id){ foreach (Item entity in itemList.ConsumableEntityList) { if (entity.ID == id) { return entity; } } foreach (Item entity in itemList.EquipmentEntityList) { if (entity.ID == id) { return entity; } } foreach (Item entity in itemList.MaterialEntityList) { if (entity.ID == id) { return entity; } } return null; } private void ParseItemsJson(){ // 從Resource資料夾中讀取Items.json TextAsset json = Resources.Load ("Items"); // 解析Json格式 itemList = JsonUtility.FromJson (json.text); // 使用foreach迴圈讀取List中的Item資料 // TODO 讀取Json有Bug } } }
Item.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Text; namespace RPG.Inventory{ [Serializable] public class ItemList{ public ListConsumableEntityList; public List EquipmentEntityList; public List MaterialEntityList; } [Serializable] public class Item : ISerializationCallbackReceiver{ public int ID; public string Name; public string ItemTypeString; public string ItemQualityString; // 目前Unity提供的JsonUtility不支援enum型別的轉換,所以此處指定為NonSerialized代表不解析 [NonSerialized] public ItemType TheItemType; [NonSerialized] public ItemQuality TheItemQuality; public string Description; public int Capacity; public int BuyPrice; public int SellPrice; public string Sprite; public void OnAfterDeserialize(){ // JSON格式解析後,將ItemTypeString,ItemQualityString轉換成enum型別 TheItemType = (ItemType)System.Enum.Parse (typeof(ItemType), ItemTypeString); TheItemQuality = (ItemQuality)System.Enum.Parse (typeof(ItemQuality), ItemQualityString); } public void OnBeforeSerialize(){} public virtual string GetToolTipText(){ string color = String.Empty; // TODO 重構這段冗長的Switch switch (TheItemQuality) { case ItemQuality.Common: color = "white"; break; case ItemQuality.Uncommon: color = "lime"; break; case ItemQuality.Rare: color = "navy"; break; case ItemQuality.Epic: color = "magenta"; break; case ItemQuality.Legendary: color = "orange"; break; case ItemQuality.Artifact: color = "red"; break; } StringBuilder text = new StringBuilder (); text.AppendFormat (" {1} \n", color, Name); text.AppendFormat ("購買價格:{0} \n", BuyPrice); text.AppendFormat ("銷售價格:{0} \n", SellPrice); text.Append (Description); return text.ToString(); } } public enum ItemType{ Consumable, Equipment, Weapon, Material } public enum ItemQuality{ Common, Uncommon, Rare, Epic, Legendary, Artifact } }
Consumable.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Text; namespace RPG.Inventory{ [Serializable] public class Consumable : Item{ public int HP; public int MP; public override string GetToolTipText (){ string text = base.GetToolTipText (); StringBuilder newText = new StringBuilder (text); newText.AppendFormat ("\n\n加血:{0} \n", HP); newText.AppendFormat ("加魔:{0} ", MP); return newText.ToString(); } } }
Equipment.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Text; namespace RPG.Inventory{ [Serializable] public class Equipment : Item { public int Strength; public int Intellect; public int Agility; public int Stamina; public string EquipmentTypeString; [NonSerialized] public EquipmentType TheEquipmentType; public void OnAfterDeserialize(){ TheEquipmentType = (EquipmentType)System.Enum.Parse (typeof(EquipmentType), EquipmentTypeString); } public void OnBeforeSerialize(){} public override string GetToolTipText (){ string text = base.GetToolTipText (); StringBuilder newText = new StringBuilder (text); // TODO 重構這段冗長的Switch string equipmentTypeText = String.Empty; switch (TheEquipmentType) { case EquipmentType.Armor: equipmentTypeText = "胸部"; break; case EquipmentType.Belt: equipmentTypeText = "腰帶"; break; case EquipmentType.Boots: equipmentTypeText = "靴子"; break; case EquipmentType.Bracer: equipmentTypeText = "護腕"; break; case EquipmentType.Head: equipmentTypeText = "頭部"; break; case EquipmentType.Leg: equipmentTypeText = "腿部"; break; case EquipmentType.Neck: equipmentTypeText = "脖子"; break; case EquipmentType.OffHand: equipmentTypeText = "副手"; break; case EquipmentType.Ring: equipmentTypeText = "戒指"; break; case EquipmentType.Shoulder: equipmentTypeText = "護肩"; break; } newText.AppendFormat ("\n\n裝備類型:{0} \n",equipmentTypeText); newText.AppendFormat ("力量:{0} \n", Strength); newText.AppendFormat ("智力:{0} \n", Intellect); newText.AppendFormat ("敏捷:{0} \n", Agility); newText.AppendFormat ("體力:{0} \n", Stamina); return newText.ToString(); } } public enum EquipmentType{ Head, Neck, Armor, Ring, Leg, Bracer, Boots, Shoulder, Belt, OffHand } }
Materials.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; namespace RPG.Inventory{ [Serializable] public class Materials : Item { } }
最後,來執行遊戲看看結果吧!把滑鼠移動到裝備上後會顯示裝備資訊,根據不同的等級的武器名稱的顏色也不同,數字部分則是用黃色來標記。
這是合成材料的標記。
這是消耗品的標記,這樣就完成了完整的Tooltip功能嘍!
留言
張貼留言