简体   繁体   中英

How can i destroy all the childs objects before creating new?

In this function i make a loop over the childs and destroy them. The problem is for example if i have 1 child and in the Inspector in the script i change the value of the childs from 1 to 10 then it will add 10 new childs to the one that was already exist. So i have now 11. And then if i change the value from 10 to 100 i will have 111 and if i change back to 1 then i will have 112.

What i want it to do while the game is running if i change the value first destroy all the childs then make the new once according to the last changed value. So if the value when i'm runinng the game is 10 and i change it to 100 first delete the 10 then add new 100. If i change from 10 to 1 first delete the 10 then add 1.

What i want to do in general is when changing the value of _birdscount while the game is running change the number of childs.

In the top of the script:

public CameraControl cameraControl;
public Object birdPrefab;
public Transform birdParent;
private Transform cameraObj;
public Transform[] instancePoints;
public int _birdscount;

In the Start function i added a StartCoroutine:

void Start()
  {
    if( globalSettings == null )
    {
      settings = LoadSettings();
      globalSettings = settings;
    }
    else
      settings = globalSettings;

    InstantiateBirds();
    cameraControl.Enabled = !settings.showSettingsWindow;

    StartCoroutine(_WatchBirdCount());
  }

Then in a function that will check if the value _birdscount changed or not and destroying the childs and create new once:

int prevBirdCount;
    List<Transform> transforms = new List<Transform>();
    IEnumerator _WatchBirdCount()
    {
        prevBirdCount = _birdscount;

        while(true)
        {
            if(_birdscount != prevBirdCount)
            {
                prevBirdCount = _birdscount;
                //Do something
                foreach (Transform child in birdParent)
                {
                    //child is your child transform
                    Destroy(child);
                }
                InstantiateBirds();
            }
            yield return 0; //Wait a frame before checking again
            {
            }
        }
    }

The InstantiateBirds() function that make the childs: I added to this function the line:

sts.BirdsCount = prevBirdCount;

Here:

void InstantiateBirds()
  {
    var ip = instancePoints[settings.instancePointNum];
    var sts = settings.boidSettings[settings.instancePointNum];

    sts.Trace = ip.GetComponent<Trace>();

    const float size = 0.1f;

    cameraObj = InstantiateBird( ip.position, ip.rotation, sts ).transform;
    cameraControl.Target = cameraObj;
         sts.BirdsCount = prevBirdCount;
    MathTools.FillSquareUniform( sts.BirdsCount, delegate ( int x, int y )
    {
      if( x != 0 || y != 0 )
        InstantiateBird(
          cameraObj.position + new Vector3( size * x, size * y, Random.Range(-size, size) ),
          MathTools.RandomYawPitchRotation(),
          sts
        );
    });
  }

And if it's needed the InstantiateBird function:

private GameObject InstantiateBird( Vector3 position, Quaternion rotation, Boid.Settings boidSettings )
  {
    var obj = (GameObject)Instantiate( birdPrefab, position, rotation );
    var boid = obj.GetComponent<Boid>();

    obj.transform.parent = birdParent;
    boid.SettingsRef = boidSettings;
    boid.DebugSettingsRef = settings.debugSettings;

    return obj;
  }

Something along these lines should do that:

public void ClearChilds(Transform parent)
{
    foreach(Transform child in parent)
    {
        Destroy(child.gameObject);
    }
}

You do have these lines in your code with a little difference: You only call Destroy on the transform ( child ), not the gameobject ( child.gameObject ).

EDIT:
I wrote a little code that will update the number of children of the object the script is on according to the number of the public field ( childCount ). currentChildCount is just for testing public (this is your prevBirdCount ). This script will destroy all old children first and then instantiate new ones.

For testing this code, you just need some object as parent that you place this script on and some prefab that serves as child. (I don't fiddle with positioning.)

using UnityEngine;
using System.Collections;

public class ChildrenHandler : MonoBehaviour {

    public GameObject childPrefab;

    public int childCount;

    public int currentChildCount;

    // Use this for initialization
    void Start ()
    {
        InstantiateChildren(childCount);

        StartCoroutine(CheckChildCount());
    }

    IEnumerator CheckChildCount()
    {
        currentChildCount = childCount;

        while(true)
        {
            if(childCount != currentChildCount)
            {
                foreach(Transform child in transform)
                {
                    Destroy(child.gameObject);
                }

                InstantiateChildren(childCount);
            }
            yield return null;
        }   
    }

    private void InstantiateChildren(int num)
    {
        for(int i = 0; i < num; i++)
        {
            GameObject go = (GameObject)Instantiate(childPrefab, transform.position, Quaternion.identity);
            go.transform.SetParent(transform);
        }

        currentChildCount = childCount;
    }
}

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