Related Posts Plugin for WordPress, Blogger...

5-16 Character Property Panel

本章要來講講顯示人物屬性的視窗,主要是從背包內裝上裝備後,必須要更新人物屬性數值。首先,讓我們在Character Panel中新增一個UI/Panel。

新的Panel取名為Property Panel,然後在底下新增一個UI/Text,這是要用來顯示人數屬性的。

然後,Text的Anchor Presets請設定成stretch stretch。

然後請大家自己調整一下文字的大小、顏色。

最後,大致上做成如下圖的模樣,Property Panel的背景底圖就請大家自己找找吧。

接著,新增一個Script名為CharacterProperty.cs。

CharacterProperty.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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
namespace RPG.Inventory{
 public class CharacterProperty : MonoBehaviour {
 
  [SerializeField] int baseStrength = 10;
  [SerializeField] int baseIntellect = 10;
  [SerializeField] int baseAgility = 10;
  [SerializeField] int baseStamina = 10;
 
  Text propertyText;
  InventorySystem inventorySystem;
 
  void Start(){
   propertyText = GetComponent<text> ();
   inventorySystem = GetComponentInParent<inventorysystem> ();
  }
 
  public void UpdatePropertyText(){
   int strength = 0;
   int intellect = 0;
   int agility = 0;
   int stamina = 0;
 
   Slot[] slotList = inventorySystem.GetSlotList ();
   if (slotList.Length == 0) {
    return;
   }
 
   foreach (Slot slot in slotList) {
    EquipmentSlot equipmentSlot = (slot as EquipmentSlot);
    if (equipmentSlot && slot.transform.childCount > 0) {
     Item item = slot.transform.GetComponentInChildren<itemui> ().Item;
     if (item is Equipment) {
      Equipment equipment = (item as Equipment);
      strength += equipment.Strength;
      intellect += equipment.Intellect;
      agility += equipment.Agility;
      stamina += equipment.Stamina;
     }
    }
   }
   strength += baseStrength;
   intellect += baseIntellect;
   agility += baseAgility;
   stamina += baseStamina;
   string text = string.Format ("力量:{0}\n智力:{1}\n敏捷:{2}\n體力:{3}",
    strength, intellect, agility, stamina);
   propertyText.text = text;
  }
 }
}
</itemui></inventorysystem></text>

然後將CharacterProperty.cs拉進Text底下。

接著修改InventorySystem.cs,主要變動的地方如下圖,僅是新增了一個方法用來呼叫CharacterProperty的UpdatePropertyText方法。
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
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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.UI;
using UnityEngine.EventSystems;
 
namespace RPG.Inventory{
 public class InventorySystem : MonoBehaviour {
 
  [SerializeField] ToolTip toolTip;
  [SerializeField] ItemUI pickedItem;
  [SerializeField] CharacterProperty characterProperty;
 
  public bool isPickedItem = false;
  ItemList itemList;
  Slot[] slotList;
 
  void Start () {
   ParseItemsJson ();
   slotList = GetComponentsInChildren<slot> ();
  }
 
  void Update(){
   PressGToAddItem ();
   MovePickedItemByMousePosition ();
   DiscardPickedItem ();
  }
 
  public void PickupItem(Item item, int amount){
   pickedItem.SetItem (item, amount);
   pickedItem.Show ();
   toolTip.Hide ();
   isPickedItem = true;
  }
 
  public void ReducePickedItem(int amount){
   pickedItem.ReduceAmount(amount);
   if (pickedItem.Amount <= 0) {
    isPickedItem = false;
    pickedItem.Hide ();
   }
  }
 
  public void WearingEquipment(ItemUI equipmentToWear){
   if ((equipmentToWear.Item is Equipment) == false) {
    return;
   }
 
   foreach(Slot slot in slotList){
    EquipmentSlot equipmentSlot = (slot as EquipmentSlot);
    if(equipmentSlot && equipmentSlot.EquipmentTypeIsEqual (equipmentToWear.Item)){
     if (equipmentSlot.transform.childCount > 0) {
      // 人物已配戴裝備了,將裝備與背包的裝備交換
      equipmentSlot.GetComponentInChildren<itemui> ().ExchangeItem(equipmentToWear);
     } else {
      // 人物未配戴裝備,直接穿上
      equipmentSlot.StoreItem (equipmentToWear.Item);
      // 銷毀背包內的裝備
      Destroy (equipmentToWear.gameObject);
     }
     break;
    }
   }
   UpdatePropertyText ();
  }
 
  public ItemUI GetPickedItem(){
   return pickedItem;
  }
 
  public Slot[] GetSlotList(){
   return slotList;
  }
 
  public void ShowToolTip(string content){
   toolTip.Show (content);
  }
 
  public void HideToolTip(){
   toolTip.Hide ();
  }
 
  public void UpdatePropertyText(){
   characterProperty.UpdatePropertyText ();
  }
 
  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 void PressGToAddItem(){
   // 測試程式碼,手動生成物品
   if (Input.GetKeyDown (KeyCode.G)) {
    StoreItem (Random.Range(1,17));
   }
  }
 
  private void MovePickedItemByMousePosition(){
   if (isPickedItem) {
    // 將滑鼠座標轉換成Canvas上的座標
    Vector2 position;
    Canvas canvas = GetComponentInParent<canvas> ();
    RectTransformUtility.ScreenPointToLocalPointInRectangle (
     canvas.transform as RectTransform,
     Input.mousePosition,
     null,
     out position);
    pickedItem.SetLocalPosition (position);
   }
  }
 
  private void DiscardPickedItem(){
   // 處理物品丟棄
   // IsPointerOverGameObject(-1)判斷滑鼠左鍵是否有碰到GameObject
   if (pickedItem && Input.GetMouseButtonDown (0)
    && EventSystem.current.IsPointerOverGameObject(-1) == false) {
    // TODO 跟Slot.cs的PickupAllSlotItem相衝突,若用DestroyImmediate會導致此方法被呼叫
    isPickedItem = false;
    pickedItem.Hide ();
   }
  }
 
  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);
  }
 }
}
</itemlist></textasset></canvas></itemui></slot>

修改完以後,記得在Canvas的InventorySystem中,要設定Character Property屬性,將Text拉進去。

最後,我們在EquipmentSlot.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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
 
namespace RPG.Inventory{
 public class EquipmentSlot : Slot {
  [SerializeField] public EquipmentType equipmentType;
 
  public override void OnPointerDown(PointerEventData eventData){
   // 使用滑鼠右鍵自動脫下裝備
   if (eventData.button == PointerEventData.InputButton.Right
    && invetorySystem.isPickedItem == false && transform.childCount > 0) {
 
    ItemUI clickedItemUI = GetComponentInChildren<itemui> ();
    invetorySystem.StoreItem (clickedItemUI.Item);
    DestroyImmediate (clickedItemUI.gameObject);
    invetorySystem.UpdatePropertyText ();
   }
 
   if (eventData.button != PointerEventData.InputButton.Left) {
    return;
   }
 
   if (invetorySystem.isPickedItem == true) {
    Item pickedItem = invetorySystem.GetPickedItem ().Item;
    //  判斷手上的裝備類型是否與該Slot的裝備類型相同
    if (EquipmentTypeIsEqual (pickedItem)) {
     if (transform.childCount > 0) {
      // 若裝備槽有東西,將手上的物品與裝備槽交換
      ItemUI clickedItemUI = transform.GetChild (0).GetComponent<itemui> ();
      invetorySystem.GetPickedItem ().ExchangeItem (clickedItemUI);
      invetorySystem.UpdatePropertyText ();
     } else {
      // 若裝備槽沒東西,直接把手上的東西放進去
      PutInOneItem();
      invetorySystem.UpdatePropertyText ();
     }
    }
   } else {
    if (transform.childCount > 0) {
     // 若裝備槽有東西,將裝備拿到手上
     ItemUI clickedItemUI = transform.GetChild (0).GetComponent<itemui> ();
     PickupAllSlotItem(clickedItemUI);
     invetorySystem.UpdatePropertyText ();
    }
   }
  }
 
  public bool EquipmentTypeIsEqual(Item item){
   return item is Equipment && (item as Equipment).TheEquipmentType == equipmentType;
  }
 }
}
</itemui></itemui></itemui>


留言