using UnityEngine;
using System.Collections;
public class TestRemoveChild : MonoBehaviour
{
public void Update()
{
if( Input.GetKeyDown( KeyCode.Y ) )
{
RemoveChild();
}
}
public void RemoveChild()
{
foreach( Transform child in transform )
{
Debug.Log( "child : " + child.name + "
" );
if( child.name == "Child_1" ) // Or some given condition
child.parent = null;
// Next child won't be enumerated
}
}
}
If we set the parent of a transform in a foreach loop of the parent, the next child is not enumerated.
I know removing an item while enumerating is not generally a good idea. But Unity don't even throw a warning about that, either in the doc or at runtime.
On the other hand, C# or Mono throws an exception when we do something like that.
And I just spent an afternoon figuring why some object was correctly suppressed when some other doesn't while both of them pass the condition :-(.
A simple example depicting the suggestion put by Jessy.
public void RemoveChild()
{
List<Transform> unparent = new List<Transform>(transform.childCount);
foreach (Transform child in transform)
{
if (child.name == "Child_1")
unparent.Add(child);
}
foreach (Transform child in unparent)
{
child.parent = null;
}
}
Extra reading that is slowly but steadily going off topic ahead:
You can make use of predicates to allow to unparent a child following an arbitrary test:
public void UnparentChildren(System.Func<Transform, bool> predicate)
{
List<Transform> unparent = new List<Transform>(transform.childCount);
foreach (Transform child in transform)
{
if (predicate(child))
unparent.Add(child);
}
foreach (Transform child in unparent)
{
child.parent = null;
}
}
And use it as such:
// Unparents children named Child_1
// Unparents children tagged Enemy
UnparentChildren(t => t.name == "Child_1");
UnparentChildren(t => t.tag == "Enemy");
// Or do it like this, combined, "if name is Child_1 or if tag is Enemy":
UnparentChildren(t => t.name == "Child_1" || t.tag == "Enemy");
And you can even make it a bit more reusable if you also provide an action so you can do other things that just unparenting them:
// Assume using System;
public void ForEachChildThat(Func<Transform, bool> predicate,
Action<Transform> action)
{
List<Transform> children = new List<Transform>(transform.childCount);
foreach (Transform child in transform)
{
if (predicate(child))
children.Add(child);
}
foreach (Transform child in children)
{
action(child);
}
}
Then you could do:
// Unparens children named Child_1
// Calls OnShakeOff on children tagged Enemy
ForEachChildThat(t => t.name == "Child_1", t => t.parent = null);
ForEachChildThat(t => t.tag == "Enemy", t => t.SendMessage("OnShakeOff"));
This is an old question, but, here is how I deal with operating on children in a foreach loop a bit cleanly. Just add an extension method for Transform. Drop this class in your project:
using UnityEngine;
using System.Collections.Generic;
public static class TransformExtensions {
public static Transform[] GetChildren(this Transform transform) {
List<Transform> children = new List<Transform>();
foreach (Transform child in transform) {
children.Add(child);
}
return children.ToArray();
}
}
And use it like this:
foreach(Transform child in myTransform.GetChildren()) {
child.SetParent(someOtherTransform);
}
It’s pretty much the same thing as the accepted answer, except it eliminates having to write two foreach loops everything you need to operate on children.
Forgive me for the necro, but I’m baffled with how needlessly complicated and wasteful the previous solutions were. For anyone who might end up here, you can just do:
transform.DetachChildren();
If you want to move the children to some other parent, you can do simply:
while (transform.childCount > 0)
transform.GetChild(0).parent = newParent;