im getting the warning: You are trying to create a MonoBehaviour using the 'new' keyword [duplicate]

。_饼干妹妹 提交于 2021-02-15 07:58:10

问题


The full warning msg:

You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all

Im trying to make an inventory to my game i followed the code from BLACKTHORNPROD but there is no stack item so i'm trying to modify the code. This is the Inventory script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Inventory : MonoBehaviour
{
    public int[] items;

    public List<Pickup> itemList;
    public GameObject[] slots;
    void start(){

    }
    void Update(){

        // Debug.Log(itemList); 
    }

    public Inventory(){
        itemList = new List<Pickup>();
    }
    public List<Pickup> GetItemList(){
        return itemList;
    }

    public void AddItem(Pickup item, int i, GameObject itemButton){
        if (item.IsStackable()){
            bool itemAlreadyInInventory = false;
            foreach (Pickup InventoryItem in itemList){
                if(InventoryItem.itemType == item.itemType){
                    InventoryItem.amount += item.amount;
                    itemAlreadyInInventory= true;
                }
            }
            if(!itemAlreadyInInventory){
            itemList.Add(item);

            items[i] = 1;
            Instantiate(itemButton, slots[i].transform, false);
            }
        }else{
        itemList.Add(item);

        items[i] = 1;
        Instantiate(itemButton, slots[i].transform, false);
        }
    }
}

The pickup Script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Pickup : MonoBehaviour
{


    public ItemType itemType;
    public int amount;
    // public ItemType[] itemTypes;
    private Inventory inventory;
    private GameObject slots;
    public GameObject itemButton;


    // Start is called before the first frame update
    private void Start()
    {
        slots = GameObject.FindGameObjectWithTag("Player");
        inventory = GameObject.FindGameObjectWithTag("Player").GetComponent<Inventory>();

    }

    private void OnTriggerEnter2D(Collider2D other)
    {

        if (other.CompareTag("Player"))
        {
            for (int i = 0; i < inventory.items.Length; i++)
            {
                if (inventory.items[i] == 0)
                {
                    inventory.AddItem(new Pickup { itemType = itemType, amount = 1 }, i, itemButton);
                    Destroy(gameObject);
                    break;

                }
            }
        }


    }

    public bool IsStackable()
    {
        switch (itemType)
        {
            default:
            case ItemType.Arrow:
                return true;

            case ItemType.Bow:
            case ItemType.Sword:
                return false;
        }
    }
    public enum ItemType
    {
        Bow,
        Arrow,
        Sword,

    }
}

回答1:


As I see it the problem is this line:

itemList = new List<Pickup>();

You need to understand that if you add MonoBehaviour to a class then you cannot create them using "new" (As the warning message tells you). It helps to think of the PickUp-class as an UI-Element.




回答2:


The error is obviously coming from

inventory.AddItem(new Pickup { itemType = itemType, amount = 1 }, i, itemButton);

and probably also from

public Inventory()
{
    itemList = new List<Pickup>();
}

it tells you exactly what is wrong so I guess that is not in question here. MonoBehaviour may not be instantiate via new nor have any constructor! The only way to create instances is by either using AddComponent, Instantiate or via the GameObject constructor.


To solve this you should simply not use a List<Pickup> but rather separate the data from the behavior e.g.:

public enum ItemType
{
    Bow,
    Arrow,
    Sword,
}

// This will be the data type you pass on and store in your inventory
[Serializable]
public struct PickUpData
{
    public ItemType itemType;
    public int amount;
}

Then in the inventory

public class Inventory : MonoBehaviour
{
    public int[] items;

    public List<PickUpData> itemList = new List<PickUpData>();
    public GameObject[] slots;

    // Note: Remove empty Unity message methods they are just overhead

    // Note: Inventory is a MonoBehaviour and therefore may not have any constructor!

    // Do you need this? itemList  is public anyway ...
    public List<PickupData> GetItemList()
    {
        return itemList;
    }

    public void AddItem(PickUpData item, int i, GameObject itemButton)
    {
        if (item.IsStackable())
        {
            var itemAlreadyInInventory = false;
            foreach (Pickup InventoryItem in itemList)
            {
                if(InventoryItem.itemType == item.itemType)
                {
                    InventoryItem.amount += item.amount;
                    itemAlreadyInInventory= true;
                }
            }

            if(!itemAlreadyInInventory)
            {
                itemList.Add(item);

                items[i] = 1;
                Instantiate(itemButton, slots[i].transform, false);
            }
        }
        else
        {
            itemList.Add(item);

            items[i] = 1;
            Instantiate(itemButton, slots[i].transform, false);
        }
    }
}

and then in the Pickup instead have a field of PickUpData which you can configrue just the same as the direct fields before and then pass it on

public class Pickup : MonoBehaviour
{
    // This will hold the data you pass on and store in the inventory
    // Since the struct is serializable and public this will be initialized with a valid
    // reference by default
    public PickUpData data;

    private Inventory inventory;
    private GameObject slots;
    public GameObject itemButton;

    // Start is called before the first frame update
    private void Start()
    {
        slots = GameObject.FindGameObjectWithTag("Player");
        inventory = GameObject.FindGameObjectWithTag("Player").GetComponent<Inventory>();
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            for (int i = 0; i < inventory.items.Length; i++)
            {
                if (inventory.items[i] == 0)
                {
                    inventory.AddItem(data, i, itemButton);
                    Destroy(gameObject);
                    break;
                }
            }
        }
    }

    public bool IsStackable()
    {
        switch (itemType)
        {
            case ItemType.Bow:
            case ItemType.Sword:
                return false;

            // default should always be on the bottom
            case ItemType.Arrow:
            default:
                return true;
        }
    }
}


来源:https://stackoverflow.com/questions/62015651/im-getting-the-warning-you-are-trying-to-create-a-monobehaviour-using-the-new

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!