1. 程式人生 > >UNITY->(width*height)style Inventory

UNITY->(width*height)style Inventory

 

專案過後對專案功能進行記錄,(width*height)風格揹包實現細節,包含對物體的存放,裝備,替換,對未知裝備的鑑定,物體字首的獲取,專案型別為tcg+rpg,揹包的作用主要為遊戲中的物品的獲取存放,卡牌的獲取管理,對可疊加物品的存放,(width*height)的目的為對物品的存放管理,其效果如下

 

  1. 基礎物品 (width*height) 

     物品的建立通過ScriptObject進行建立,根據物品型別設計相關的尺寸(width*height),利用deepcopy建立實體存放如揹包,專案的物品管理通過一個獨立的類

ItemDatabase進行管理,在玩家獲取一個新物品(未鑑定),通過一個隨機生成類來產生詞綴和屬性

    本專案物品的生成通過deepcopy生成物品並新增進itemdatabse,Itemdatabase的作用對遊戲物品資產的管理以及生成,有利於未知裝備的生成,在對商品商管理上,新增未知隨機的裝備可以為遊戲的物品提高遊戲性

    

public static ItemClass DeepCopy(ItemClass obj) {
        GameObject oj = obj.worldObject;
                //ItemClass is item base class
        ItemClass i = (ItemClass)Process(obj);
        i.worldObject = oj;
        return i;
    }
    
    static object Process(object obj) {
        if(obj==null)
            return null;
        Type type=obj.GetType();
        if(type.IsValueType || type==typeof(string)) {
            return obj;
        }
        else if(type.IsArray) {
            Type elementType=Type.GetType(
                type.FullName.Replace("[]",string.Empty));
            var array=obj as Array;
            Array copied=Array.CreateInstance(elementType,array.Length);
            for(int i=0; i<array.Length; i++) {
                copied.SetValue(Process(array.GetValue(i)),i);
            }
            return Convert.ChangeType(copied,obj.GetType());
        }
        else if(type.IsClass) {
            object toret=Activator.CreateInstance(obj.GetType());
            FieldInfo[] fields=type.GetFields(BindingFlags.Public| 
                                              BindingFlags.NonPublic|BindingFlags.Instance);
            foreach(FieldInfo field in fields) {
                object fieldValue=field.GetValue(obj);
                if(fieldValue==null)
                    continue;
                field.SetValue(toret, Process(fieldValue));
            }
            return toret;
        }
        else
            throw new ArgumentException("Unknown type");
    }    

 

             

  2.生成slot並將物品存放進slot(width*height)

    在物品新增進揹包時,根據幾個條件進行判斷

        1.slot是否能填充進去

          在物品新增進揹包欄,需要檢測物品尺寸是否越過揹包限制並物品之間是否存在重疊,重疊狀態一般在物品編輯器中設定(通常為藥水...),當不可疊加物品存在重疊狀態中,獲取狀態顏色並提示狀態

//檢測邊界以及疊加狀態
public bool CheckItemFit(ItemClass item, InventorySlot slot, bool skipLastCheck) {
        //Run through all the slots that the item occupies
        for(int i = 0; i < item.height; i++) {
            for(int j = 0; j < item.width; j++) {
                //Check if the slot exists
                if(slot.itemStartNumber + inventoryWidth * i + j >= items.Count) {
                    return false;
                }
                //Check to see if the first slot is located at the edge of the inventory
                for(int k = 0; k < item.height; k++) {
                    if(slot.itemStartNumber + inventoryWidth * k + j != slot.itemStartNumber + inventoryWidth * k) {
                        if(((slot.itemStartNumber + inventoryWidth * i + j ) % inventoryWidth == 0) && item.width != 1) {
                            return false;
                        }
                    }
                }
                //Last check is only used sometimes
                //Checks to see if there's already something in the slots
                if(!skipLastCheck) {
                    if(items[slot.itemStartNumber + inventoryWidth * i + j].itemStartNumber != slot.itemStartNumber + inventoryWidth * i + j) {
                        return false;
                    }
                }
                else {
                    List<int> counter = new List<int>();
                    for(int l = 0; l < item.height; l++) {
                        for(int m = 0; m < item.width; m++) {
                            if((slot.itemStartNumber + inventoryWidth * (item.height - 1) + (item.width - 1)) < items.Count - 1 && items[slot.itemStartNumber + inventoryWidth * l + m].itemStartNumber != slot.itemStartNumber && items[slot.itemStartNumber + inventoryWidth * l + m].item.itemName != "" && !counter.Contains(items[slot.itemStartNumber + inventoryWidth * l + m].itemStartNumber)) {
                                counter.Add(items[slot.itemStartNumber + inventoryWidth * l + m].itemStartNumber);
                            }
                        }
                    }
                    if(counter.Count > 1) {
                        //return false if there's more than one item
                        return false;
                    }
                    else if(counter.Count == 1) {
                        return true;
                    }
                }
            }
        }
        return true;
    }

    當物品狀態為可新增時,新增進slot,根據width*height尺寸進行新增

  

for(int l = 0; l < item.height; l++) {
                        for(int m = 0; m < item.width; m++) {
                            //First we add the items to the slots the it fills and set their slots to clear
                            items[i + inventoryWidth * l + m].item = DeepCopy(item);
                            items[i + inventoryWidth * l + m].itemStartNumber = i;
                            items[i + inventoryWidth * l + m].GetComponent<Image>().color = Color.clear;
                            items[i + inventoryWidth * l + m].stacksizeText.gameObject.SetActive(false);
                            //If it's the first index of the added item
                            if(items.IndexOf(items[i + inventoryWidth * l + m]) == i) {
                                SetSlotImageSprite(items[i + inventoryWidth * l + m], item.icon);
                                items[i + inventoryWidth * l + m].itemFrame.gameObject.SetActive(true);
                                items[i + inventoryWidth * l + m].itemFrame.GetComponent<CanvasGroup>().interactable = true;
                                items[i + inventoryWidth * l + m].itemFrame.GetComponent<CanvasGroup>().blocksRaycasts = true;
                                items[i + inventoryWidth * l + m].GetComponent<CanvasGroup>().blocksRaycasts = true;
                                items[i + inventoryWidth * l + m].itemFrame.rectTransform.sizeDelta = new Vector2(item.width * slotIconSize, item.height * slotIconSize);
                                //If the item is stackable
                                if(item.stackable) {
                                    items[i + inventoryWidth * l + m].stacksizeText.gameObject.SetActive(true);
                                    items[i + inventoryWidth * l + m].stacksizeText.text = item.stackSize.ToString();
                                }
                                //The item is unidentified
                                if(item.unidentified) {
                                    items[i + inventoryWidth * l + m].itemImage.color = Color.red;
                                    items[i + inventoryWidth * l + m].unidentified.gameObject.SetActive(true);
                                }
                            }
                        }
                    }

      2.物品是否存在物品

          當物品存在物品時,需要對存在物品的佔用尺寸進行判斷(int slot=indexof(item)),當slot存在物品時,遍歷slot.count 獲取空欄位並存放,另外一種情況是當玩家處於dragging狀態時,可以對物品進行替換,存放在物品的方式一般為

        

Items[slot.itemStartNumber + inventoryWidth * l + m].item.variables