库存物品实施

时间:2017-07-24 00:22:42

标签: c# unity3d

目前我有一个像这样工作的库存实现 - 有一个名为Item基类,它是库存数组包含的内容,然后有WeaponConsumable继承自{{ 1}} ,然后Item继承自Gun 。但是,我有一个问题,我希望项目具有可变属性的意义,我希望Weapon类保持枪中的弹药数量,但如果它被更改,那么考虑它是使用相同的类实例然后它将改变库存中所有特定类型枪支的弹药。我听说过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;

1 个答案:

答案 0 :(得分:0)

Json&amp;类型方法

正如我之前评论的那样,可以使用json和Type来创建字典并克隆已注册的对象。我已经改变了你的代码来做到这一点。见下文:

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函数中返回该项的副本,而不是在Items中返回对原始对象的引用。您甚至不需要存储原件。

试试这个get函数:

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

如果您需要在运行时注册项目,我建议将它们序列化为JSON并存储JSON和Type。以下链接可能有助于此:

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