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的原始碼如下:

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 ();
   inventorySystem = GetComponentInParent ();
  }

  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 ().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;
  }
 }
}

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

接著修改InventorySystem.cs,主要變動的地方如下圖,僅是新增了一個方法用來呼叫CharacterProperty的UpdatePropertyText方法。
InventorySystem.cs:

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 ();
  }

  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 ().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 ();
    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 ("Items");
   // 解析Json格式
   itemList = JsonUtility.FromJson (json.text);
  }
 }
}

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

最後,我們在EquipmentSlot.cs中,有一些穿脫裝備的地方需要更新人物屬性。

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 ();
    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 ();
      invetorySystem.GetPickedItem ().ExchangeItem (clickedItemUI);
      invetorySystem.UpdatePropertyText ();
     } else {
      // 若裝備槽沒東西,直接把手上的東西放進去
      PutInOneItem();
      invetorySystem.UpdatePropertyText ();
     }
    }
   } else {
    if (transform.childCount > 0) {
     // 若裝備槽有東西,將裝備拿到手上
     ItemUI clickedItemUI = transform.GetChild (0).GetComponent ();
     PickupAllSlotItem(clickedItemUI);
     invetorySystem.UpdatePropertyText ();
    }
   }
  }

  public bool EquipmentTypeIsEqual(Item item){
   return item is Equipment && (item as Equipment).TheEquipmentType == equipmentType;
  }
 }
}


留言