- Home /
Why does this function still reference a destroyed child?
[Initial question deleted, it was not the root of the problem, see edit.]
Edit: Quick explaination, this script is one that assigns a cursor object to the mouse. On selection of a new cursor object this script is called, where the old cursorobject is deleted and a new one added: it would seem that the problem actually lies with the previous "mousecursor" object, which is getting destroyed, is still being referenced?:
public void SetObjToPlace(GameObject obj)
{
objToPlace = obj;
cursorChildren = GetComponentsInChildren<Transform>();
// Clear collisionScripts
collisionScripts.Clear();
// Delete old object cursor
if (cursorChildren != null)
{
foreach (Transform child in transform)
{
Destroy(child.gameObject);
// ^ THIS OBJECT STILL GETS REFERENCED IN AddRigidBodyAndTriggerToAllChildren
}
cursorChildren = GetComponentsInChildren<Transform>();
}
// Create new object cursor
GameObject newCursor = Instantiate(obj);
newCursor.transform.parent = transform;
AddRigidBodyAndTriggerToAllChildren(transform);
// ^ This ^ function throws the error "Can't add component 'Rigidbody' to NameOfPreviouslyDestroyedObject because such a component is already added to the game object (well no shit, but it shouldn't check that destroyed child)
transform.rotation = Quaternion.identity;
newCursor.transform.position = transform.position;
SetChildShader();
}
private void AddRigidBodyAndTriggerToAllChildren(Transform parent)
{
foreach (Transform child in parent)
{
BoxCollider[] childColliders = child.gameObject.GetComponents<BoxCollider>();
if (childColliders.Length > 0)
{
Rigidbody childRB = child.gameObject.AddComponent<Rigidbody>();
// ^ This is the line throwing the error ^
childRB.useGravity = false;
// ^ Causing a nullref for childRB here
childRB.isKinematic = true;
PlacementCollision collisionScript = child.gameObject.AddComponent<PlacementCollision>();
collisionScripts.Add(collisionScript);
foreach (BoxCollider collider in childColliders)
{
collider.isTrigger = true;
}
}
AddRigidBodyAndTriggerToAllChildren(child);
}
}
Are you sure you simply don't call the function twice?
Add a Debug.Log outside the loop
Answer by mangosauce_ · Mar 19, 2021 at 07:00 PM
A simpler way to do what you're trying, while also ensuring transforms aren't referenced more than once, is to use GetComponentsInChildren.
// This retrieves children, grandchildren, great-grandchildren, etc.
Transform[] children = GetComponentsInChildren<Transform>();
foreach (Transform child in children)
{
// Execute code with child
}
Otherwise you can store the child Transforms already collected in a List, then check if the child has already been added to the list before performing a function.
Would for example GetComponentsInChildren() also get 2 box colliders if a single child has 2 of that component attached?
I believe it would, yes. If you're looking to get a specific box collider (or any component type you have multiple of attached to a single game object) you might need to get creative and attach a script to the object that can resolve which component to return.
For example, instead of GetComponentsInChildren(BoxCollider) you might use GetComponentsInChildren(BoxColliderResolver), which would be a script attached to game objects with multiple box colliders. Then you can retrieve the correct collider by calling a method like _colliderResolver.Resolve().
Just a thought though, you probably won't need to get that complicated with it. :P
Nah I think GetComponentsInChildren is what I am looking for then, previously I was using this function in combination with GetComponents.
Note:
GetComponentInChildren returns the components attached to the gameObject and the children.
https://docs.unity3d.com/ScriptReference/Component.GetComponentsInChildren.html
Follow this Question
Related Questions
Is there any way to use parenting as an organization tool without creating a Transform bond? 3 Answers
Destroy(other.gameObject) isn't destroying parent, only children 2 Answers
Target child of child without knowing name? 1 Answer
Make a simple tree 1 Answer
onTriggerEnter is unclear to me... 3 Answers