2017-07-24 68 views
1

目前,我有一個庫存的實現,是這樣工作的 - 有一個叫Item一個基類,這就是庫存數組包含,則有WeaponConsumableItem繼承然後從Weapon繼承Gun。但是,我有一個問題,我想的項目有多變的性質意義,我想Gun類持有槍的彈藥量,但是如果改變,那麼考慮它使用的類的同一個實例,然後它會改變彈藥庫存中所有具體類型的槍支。我聽說ICloneable,但它顯然貶值,不應使用。庫存項目實施

我的項目腳本:

using UnityEngine; 
using System.Collections.Generic; 

public class Items : MonoBehaviour 
{ 
    static Dictionary<int, Item> items = new Dictionary<int, Item>(); 

    private static bool initialized; 

    [SerializeField] 
    Texture2D[] itemIcons; 

    private void Start() 
    { 
     Gun desertEagle = new Gun(); 
     desertEagle.damage = 40; 
     desertEagle.range = 20; 
     desertEagle.maxAmmunition = 7; 
     desertEagle.firemode = FireMode.Semi; 
     desertEagle.firerate = 1; 

     desertEagle.name = "Desert Eagle"; 
     desertEagle.description = "Desert Eagle (.50 Cal) is a semi-automatic pistol with an ammo capacity of 7 rounds"; 
     desertEagle.equippable = true; 
     desertEagle.icon = itemIcons[1]; 

     Consumable donut = new Consumable(); 
     donut.food = 30; 

     donut.name = "Donut"; 
     donut.description = "A ring full of legendary awesomeness"; 
     donut.equippable = true; 
     donut.icon = itemIcons[2]; 

     Consumable coffee = new Consumable(); 
     coffee.water = 30; 
     coffee.stamina = 50; 

     coffee.name = "Coffee"; 
     coffee.description = "A delicious beverage to help you get up in the morning. Goes well with donuts."; 
     coffee.equippable = true; 
     coffee.icon = itemIcons[3]; 

     RegisterItem(1, desertEagle); 
     RegisterItem(2, donut); 
     RegisterItem(3, coffee); 

     initialized = true; 
    } 

    public static void RegisterItem(int id, Item item) 
    { 
     items.Add(id, item); 
    } 

    public static void UnregisterItem(int id) 
    { 
     items.Remove(id); 
    } 

    public static Item GetItem(int id) 
    { 
     return items[id]; 
    } 
} 

public class ItemStack 
{ 

    Item item; 
    int amount; 
    int max = 10; 

    public void Add(int amount) 
    { 
     if (item.stackable && this.amount + amount <= max) this.amount += amount; 
     else if (item.stackable) this.amount = max; 
    } 

    public void Remove(int amount) 
    { 
     if (item.stackable) this.amount -= amount; 
    } 
} 

public class Item 
{ 
    public string name = "Item"; 
    public string description = "Your everyday standard item."; 
    public bool equippable = false; 
    public bool stackable = true; 
    public Mesh model; 
    public Texture2D icon; 
} 

public class Weapon : Item 
{ 
    public float damage = 5; 
    public float range = 1; 
} 

public class Gun : Weapon 
{ 
    public int ammunition = 1; 
    public int maxAmmunition = 1; 
    public FireMode firemode = FireMode.Semi; 
    public int firerate = 1; 
    public new float range = 10; 
} 

public enum FireMode 
{ 
    Semi, 
    Automatic, 
    Burst 
} 

public class Consumable : Item 
{ 
    public float food; 
    public float water; 
    public float health; 
    public float stamina; 
}using UnityEngine; 
using System.Collections.Generic; 

我的存貨清單代碼:

Item[] inventory; 

[SerializeField] 
int inventorySize = 16; 

inventory = new Item[inventorySize]; 
inventory[0] = Items.GetItem(1); 
inventory[1] = Items.GetItem(2); 
inventory[12] = Items.GetItem(3); 
+0

對不起,我不明白你想要什麼。正如附註一樣,你可以考慮讓你的'Consumable'成爲一個界面(比如'IConsumable'),它的名字就是它的意思。然後,你可以有像「咖啡」和「甜甜圈」這樣的課程來實施它。 – Alisson

+0

不知道我理解你的問題。你想共享彈藥嗎?如果你有兩隻沙漠鷹,他們就擁有你擁有的彈藥。而已?如果是這樣,你只需要使用你的彈藥作爲消耗品。 – Fenixrw

+0

基本上,如果一個項目的值是改變,因爲用於該項目的同一個實例存儲在項目列表中的值都在盤點該項目的那些改變 – ComputerFido

回答

0

的Json &類型的方法

因此,正如我之前評論說,它可以使用JSON和類型創建字典並克隆註冊的對象。我已經改變了你的代碼來做到這一點。請看下圖:

using UnityEngine; 
using System.Collections.Generic; 
using System;//Included to use Type and [Serializable] 

public class Items : MonoBehaviour 
{ 
    public struct SerializedObject //struct to hold the type of the object and the json string 
    { 
     public Type type; 
     public string json; 
    } 

    static Dictionary<int, SerializedObject> items = new Dictionary<int, SerializedObject>();//dictionary must hold both type and json string to be used with JsonUtility 

    private static bool initialized; 

    [SerializeField] 
    Texture2D[] itemIcons; 

    private void Start() 
    { 
     Gun desertEagle = new Gun(); 
     desertEagle.damage = 40; 
     desertEagle.range = 20; 
     desertEagle.maxAmmunition = 7; 
     desertEagle.firemode = FireMode.Semi; 
     desertEagle.firerate = 1; 

     desertEagle.name = "Desert Eagle"; 
     desertEagle.description = "Desert Eagle (.50 Cal) is a semi-automatic pistol with an ammo capacity of 7 rounds"; 
     desertEagle.equippable = true; 
     desertEagle.icon = itemIcons[1]; 


     Consumable donut = new Consumable(); 
     donut.food = 30; 

     donut.name = "Donut"; 
     donut.description = "A ring full of legendary awesomeness"; 
     donut.equippable = true; 
     donut.icon = itemIcons[2]; 

     Consumable coffee = new Consumable(); 
     coffee.water = 30; 
     coffee.stamina = 50; 

     coffee.name = "Coffee"; 
     coffee.description = "A delicious beverage to help you get up in the morning. Goes well with donuts."; 
     coffee.equippable = true; 
     coffee.icon = itemIcons[3]; 

     //For each object store the Type and serialize the data using JsonUtility 
     SerializedObject so_desertEagle; 
     so_desertEagle.type = desertEagle.GetType(); 
     so_desertEagle.json = JsonUtility.ToJson(desertEagle); 
     SerializedObject so_donut; 
     so_donut.type = donut.GetType(); 
     so_donut.json = JsonUtility.ToJson(donut); 
     SerializedObject so_coffee; 
     so_coffee.type = coffee.GetType(); 
     so_coffee.json = JsonUtility.ToJson(coffee); 
     RegisterItem(1, so_desertEagle); 
     RegisterItem(2, so_donut); 
     RegisterItem(3, so_coffee); 

     /*//Made this for testing 
     Item gunCopy = GetItem(1); 
     Gun desertEagle2 = (Gun) gunCopy; 
     desertEagle2.ammunition--; 

     Debug.Log(desertEagle.ammunition + "/" + desertEagle2.ammunition); 
     //Debug result is "1/0" 
     */ 
     initialized = true; 
    } 

    public static void RegisterItem(int id, SerializedObject item) 
    { 
     items.Add(id, item); 
    } 

    public static void UnregisterItem(int id) 
    { 
     items.Remove(id); 
    } 



    public static Item GetItem(int id) 
    { 
     return (Item) JsonUtility.FromJson(items[id].json, items[id].type); //Use JsonUtility to create a copy of the serialized object 
    } 
} 

[Serializable] 
public class ItemStack 
{ 

    Item item; 
    int amount; 
    int max = 10; 

    public void Add(int amount) 
    { 
     if (item.stackable && this.amount + amount <= max) this.amount += amount; 
     else if (item.stackable) this.amount = max; 
    } 

    public void Remove(int amount) 
    { 
     if (item.stackable) this.amount -= amount; 
    } 
} 

[Serializable]//JsonUtility only works with [Serializable] objects 
public class Item 
{ 
    public string name = "Item"; 
    public string description = "Your everyday standard item."; 
    public bool equippable = false; 
    public bool stackable = true; 
    public Mesh model; //I would recommend storing the meshes in another dictionary and setting a reference here 
    public Texture2D icon; 
} 

[Serializable] 
public class Weapon : Item 
{ 
    public float damage = 5; 
    public float range = 1; 
} 

[Serializable] 
public class Gun : Weapon 
{ 
    public int ammunition = 1; 
    public int maxAmmunition = 1; 
    public FireMode firemode = FireMode.Semi; 
    public int firerate = 1; 
    public new float range = 10; 
} 

[Serializable] 
public enum FireMode 
{ 
    Semi, 
    Automatic, 
    Burst 
} 

[Serializable] 
public class Consumable : Item 
{ 
    public float food; 
    public float water; 
    public float health; 
    public float stamina; 
} 

SWITH案例法

我想我已經找到了問題。您應該在GetItem函數中返回項目的副本,而不是對項目中原始對象的引用。你甚至不需要存儲原件。如果您需要註冊在運行的項目,我建議他們序列化JSON作爲和存儲JSON和類型

public static Item GetItem(int id) 
{ 
    switch(id) 
    { 
     case 1: 
      Gun desertEagle = new Gun(); 
      desertEagle.damage = 40; 
      desertEagle.range = 20; 
      desertEagle.maxAmmunition = 7; 
      desertEagle.firemode = FireMode.Semi; 
      desertEagle.firerate = 1; 

      desertEagle.name = "Desert Eagle"; 
      desertEagle.description = "Desert Eagle (.50 Cal) is a semi-automatic pistol with an ammo capacity of 7 rounds"; 
      desertEagle.equippable = true; 
      desertEagle.icon = itemIcons[1]; 
      return gun; 
     case 2: 
      Consumable donut = new Consumable(); 
      donut.food = 30; 

      donut.name = "Donut"; 
      donut.description = "A ring full of legendary awesomeness"; 
      donut.equippable = true; 
      donut.icon = itemIcons[2]; 
      return donut; 
     case 3: 
      Consumable coffee = new Consumable(); 
      coffee.water = 30; 
      coffee.stamina = 50; 

      coffee.name = "Coffee"; 
      coffee.description = "A delicious beverage to help you get up in the morning. Goes well with donuts."; 
      coffee.equippable = true; 
      coffee.icon = itemIcons[3]; 
      return coffee; 
    } 
    return null; 
} 

試試這個get函數。以下鏈接可能會有助於利用:

https://docs.unity3d.com/Manual/JSONSerialization.html

https://msdn.microsoft.com/en-us/library/system.object.gettype(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-4

+0

我會看看json的東西,但我不認爲我會使用開關,因爲這可能會相當凌亂 – ComputerFido

+0

如果您有興趣,我已經添加了解決方案與JsonUtility的答案。它已經在這裏測試過了,它工作正常。還對我所做的更改和部分代碼中的一些建議添加了一些評論。 – Fenixrw