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 List ConsumableEntityList;
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功能嘍!






留言
張貼留言