5-10 Click To Pickup Item
本篇要介紹用滑鼠點擊背包內的物體後,會將物體選取起來,如果按住Z鍵再選擇物體的話,只會選擇一半的物體。選取起來的物體,會跟著滑鼠的鼠標移動。因為這個功能同時修改的部分比較多,所以會分多篇文章介紹,本篇先介紹選取,後續篇再介紹放下。
首先在Canvas底下創造一個PickedItem,這個物件是前面章節所介紹名為的Item的Prefab,如果不知道這個Prefab怎麼製作,請先看看以前的文章:
PickedItem預設要不啟用,所以請大家在Inspector視窗中將勾勾取消。
首先簡單介紹一下Slot修改後的程式碼,主要是繼承IPointerDownHandler,並覆寫OnPointerDown方法,該方法可以偵測滑鼠按下的事件。
然後實作內容中,先用transform.childCount確認Slot內是否有Item,再用InvntorySystem類中的bool屬性isPickedItem判斷目前是否處於『Picked』狀態,如果為非,則可以將Slot內的物體取出來。其他行則有撰寫註解,請大家自己閱讀。
在InventorySystem類中,則主要新增了PickupItem方法,此方法用來將滑鼠點中的Item屬性設定到PickedItem上面。
以下提供本次修改的完整程式碼。
Slot.cs:
InventorySystem.cs:
ItemUI.cs:
程式碼修改完成後,於KanpsackPanel的InventorySystem中,我們必須將剛剛新增到Canvas底下的PickedItem拉進參數,如下圖。
接著,讓我們執行遊戲看看吧。用滑鼠點擊腰帶後,腰帶被從背包上取下來了。
移動滑鼠時,這個腰帶也會跟著滑鼠移動。
如果是按住Z鍵再點擊血量瓶的話,會發現我們只取下一半的血量瓶。
首先在Canvas底下創造一個PickedItem,這個物件是前面章節所介紹名為的Item的Prefab,如果不知道這個Prefab怎麼製作,請先看看以前的文章:
5-6 Knapsack User Interface
製作完成後,應該會在場景中看見如下圖的PickedItem物件,這是要用在滑鼠點擊物體後,會依照物體的資訊顯示在PickedItem上面,並將原本點擊的Slot上的Item移除。
PickedItem預設要不啟用,所以請大家在Inspector視窗中將勾勾取消。
首先簡單介紹一下Slot修改後的程式碼,主要是繼承IPointerDownHandler,並覆寫OnPointerDown方法,該方法可以偵測滑鼠按下的事件。
然後實作內容中,先用transform.childCount確認Slot內是否有Item,再用InvntorySystem類中的bool屬性isPickedItem判斷目前是否處於『Picked』狀態,如果為非,則可以將Slot內的物體取出來。其他行則有撰寫註解,請大家自己閱讀。
在InventorySystem類中,則主要新增了PickupItem方法,此方法用來將滑鼠點中的Item屬性設定到PickedItem上面。
以下提供本次修改的完整程式碼。
Slot.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 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; namespace RPG.Inventory{ public class Slot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler { [SerializeField] GameObject itemPrefab; public void StoreItem(Item item){ // 若Slot底下沒有Item,則Instantiate一個 if (transform.childCount == 0) { GameObject itemObject = Instantiate (itemPrefab, transform); itemObject.GetComponentInChildren<itemui> ().SetItem (item); } else { // 已存在該Item,所以增加數量即可 transform.GetComponentInChildren<itemui> ().AddAmount (); } } public int GetItemID(){ return transform.GetComponentInChildren<itemui> ().Item.ID; } public bool IsFilled(){ ItemUI itemUI = transform.GetComponentInChildren<itemui> (); return itemUI.Amount >= itemUI.Item.Capacity; } public void OnPointerEnter(PointerEventData eventData){ if (transform.childCount > 0) { Item item = GetComponentInChildren<itemui> ().Item; GetComponentInParent<inventorysystem> ().ShowToolTip (item.GetToolTipText ()); } } public void OnPointerExit(PointerEventData eventData){ GetComponentInParent<inventorysystem> ().HideToolTip (); } public void OnPointerDown(PointerEventData eventData){ InventorySystem invetorySystem = GetComponentInParent<inventorysystem> (); if (transform.childCount > 0) { // 取得目前滑鼠點擊Slot的ItemUI ItemUI currentItemUI = GetComponentInChildren<itemui> (); if (invetorySystem.isPickedItem == false ) { if (Input.GetKey (KeyCode.Z)) { // 壓住Z鍵時,只會取出一半的數量 int amountToPick = (currentItemUI.Amount+1) / 2; int amountRemained = currentItemUI.Amount - amountToPick; // 將PickedItem的ItemUI設置為目前滑鼠點中的ItemUI invetorySystem.PickupItem (currentItemUI.Item, amountToPick); if (amountRemained == 0) { Destroy (currentItemUI.gameObject); } else { currentItemUI.SetAmount (amountRemained); } } else { // 將PickedItem的ItemUI設置為目前滑鼠點中的ItemUI invetorySystem.PickupItem(currentItemUI.Item, currentItemUI.Amount); // 因為已經選中物體了,要將Slot內的ItemUI刪除 Destroy (currentItemUI.gameObject); } } } } } } </itemui></inventorysystem></inventorysystem></inventorysystem></itemui></itemui></itemui></itemui></itemui> |
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 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 | 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; [SerializeField] ItemUI pickedItem; public bool isPickedItem = false ; 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); } void Update(){ if (isPickedItem) { // 將滑鼠座標轉換成Canvas上的座標 Vector2 position; Canvas canvas = GetComponentInParent<canvas> (); RectTransformUtility.ScreenPointToLocalPointInRectangle ( canvas.transform as RectTransform, Input.mousePosition, null , out position); pickedItem.SetLocalPosition (position); } } public void PickupItem(Item item, int amount){ pickedItem.SetItem (item, amount); pickedItem.Show (); toolTip.Hide (); isPickedItem = true ; } public ItemUI GetPickedItem(){ return pickedItem; } 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></canvas></slot> |
ItemUI.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 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace RPG.Inventory{ public class ItemUI : MonoBehaviour{ public Item Item { get ; set ; } public int Amount { get ; set ; } public void SetItem(Item item, int amount = 1){ this .Item = item; this .Amount = amount; GetComponentInChildren<img> ().sprite = Resources.Load<sprite> (item.Sprite); GetComponentInChildren<text> ().text = Amount.ToString(); } public void AddAmount( int amount = 1){ this .Amount += amount; GetComponentInChildren<text> ().text = Amount.ToString(); } public void SetAmount( int amount){ this .Amount = amount; GetComponentInChildren<text> ().text = Amount.ToString(); } public void Show(){ gameObject.SetActive ( true ); } public void Hide(){ gameObject.SetActive ( false ); } public void SetLocalPosition(Vector3 localPosition){ transform.localPosition = localPosition; } } } </text></text></text></sprite> |
程式碼修改完成後,於KanpsackPanel的InventorySystem中,我們必須將剛剛新增到Canvas底下的PickedItem拉進參數,如下圖。
接著,讓我們執行遊戲看看吧。用滑鼠點擊腰帶後,腰帶被從背包上取下來了。
移動滑鼠時,這個腰帶也會跟著滑鼠移動。
如果是按住Z鍵再點擊血量瓶的話,會發現我們只取下一半的血量瓶。
留言
張貼留言