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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | { "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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | 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<slot> (); // 測試程式碼,手動生成物品 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<textasset> ( "Items" ); // 解析Json格式 itemList = JsonUtility.FromJson <itemlist>(json.text); // 使用foreach迴圈讀取List中的Item資料 // TODO 讀取Json有Bug } } } </itemlist></textasset></slot> |
Item.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Text; namespace RPG.Inventory{ [Serializable] public class ItemList{ public List<consumable> ConsumableEntityList; public List<equipment> EquipmentEntityList; public List<materials> 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 ( "<color>{1}</color>\n" , color, Name); text.AppendFormat ( "購買價格:<color yellow=" ">{0}</color>\n" , BuyPrice); text.AppendFormat ( "銷售價格:<color yellow=" ">{0}</color>\n" , SellPrice); text.Append (Description); return text.ToString(); } } public enum ItemType{ Consumable, Equipment, Weapon, Material } public enum ItemQuality{ Common, Uncommon, Rare, Epic, Legendary, Artifact } } </materials></equipment></consumable> |
Consumable.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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加血:<color yellow=" ">{0}</color>\n" , HP); newText.AppendFormat ( "加魔:<color yellow=" ">{0}</color>" , MP); return newText.ToString(); } } } |
Equipment.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 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裝備類型:<color yellow=" ">{0}</color>\n" ,equipmentTypeText); newText.AppendFormat ( "力量:<color yellow=" ">{0}</color>\n" , Strength); newText.AppendFormat ( "智力:<color yellow=" ">{0}</color>\n" , Intellect); newText.AppendFormat ( "敏捷:<color yellow=" ">{0}</color>\n" , Agility); newText.AppendFormat ( "體力:<color yellow=" ">{0}</color>\n" , Stamina); return newText.ToString(); } } public enum EquipmentType{ Head, Neck, Armor, Ring, Leg, Bracer, Boots, Shoulder, Belt, OffHand } } |
Materials.cs:
1 2 3 4 5 6 7 8 9 10 11 | using System.Collections; using System.Collections.Generic; using UnityEngine; using System; namespace RPG.Inventory{ [Serializable] public class Materials : Item { } } |
最後,來執行遊戲看看結果吧!把滑鼠移動到裝備上後會顯示裝備資訊,根據不同的等級的武器名稱的顏色也不同,數字部分則是用黃色來標記。
這是合成材料的標記。
這是消耗品的標記,這樣就完成了完整的Tooltip功能嘍!
留言
張貼留言