简体   繁体   中英

Why is my script destroying assets? Unity

In my script I instantiate obstacles (prefabs are stored at prefabObstacles array) at transforms position ( emptyTransforms array). This script is attached to gameobject which is segment of the world. This segment is dynamically instantiated and destroyed.

public class ObstaclePlacer : MonoBehaviour
{
    public int obstaclesAmmount;
    public GameObject[] prefabObstacles;
    public Transform[] emptyTransforms;
    public GameObject[] obstacles;

    void Start()
    {
        GenerateObstacles();
    }

    void GenerateObstacles()
    {
        for(int i = 0; i < Random.Range(0,obstaclesAmmount); i++)
        {
            GameObject objToSpawn = prefabObstacles[Random.Range(0, prefabObstacles.Length)];
            obstacles[i] = Instantiate(objToSpawn, (emptyTransforms[Random.Range(0, emptyTransforms.Length)].position+new Vector3(0.0f, 1.0f)), Quaternion.identity) as GameObject;
        }
    }

    void OnDestroy()
    {
        foreach(GameObject item in obstacles)
        {
            Destroy(item);
        }
    } 
}

This bug is occurring:

Destroying assets is not permitted to avoid data loss.
If you really want to remove an asset use DestroyImmediate (theObject, true);
UnityEngine.Object:Destroy(Object)
ObstaclePlacer:OnDestroy() (at Assets/Scripts/ObstaclePlacer.cs:37)

It only works if obstacles array size is fixed.

Do you know how can I fix that?
If you need more details just ask me. Thanks for help!

I think the main disconnect here is understanding how arrays work in C#. You must declare the length of the array when you initialize it, this is different than other collections such as, generic lists, which allow you to dynamically grow or shrink the list as needed. There are deeper differences between various collections and arrays, which you will want to understand before you decide which is best for your application.

This example shows how to declare and initialize an instance of both an array and generic list of type GameObjects in the context of your Behavior Script, obviously you'd want to use one or the other in your actual script.

class ObstaclePlacer : MonoBehaviour
{
    public int obstaclesAmmount;
    public GameObject [] obstaclesArray;
    public List<GameObject> obstaclesList;

    public void Start ()
    {
        var random = new System.Random();
        //Get the desired size of your array.
        obstaclesAmmount = random.Next(0, 100);
        //Initialize an array with the size of your random number
        obstaclesArray = new GameObject [obstaclesAmmount];
        //Or use a list which allows your to dynamically add elements later.
        obstaclesList = new List<GameObject> ();

        GenerateObstacles ();
    }

    void GenerateObstacles ()
    {


        for (int i = 0; i < obstaclesAmmount; i++) {

            var gameObject = new GameObject();

            obstaclesArray[i] = gameObject;

            obstaclesList.Add(gameObject);
        }
    }

    void OnDestroy ()
    {
        foreach (GameObject item in obstaclesArray) {
            //Destroy (item);
            Console.WriteLine ("Destroy (item); in obstaclesArray");
        }

        foreach (GameObject item in obstaclesList) {
            //Destroy (item);
            Console.WriteLine ("Destroy (item); in obstaclesList");
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM