Daniel Lip
Daniel Lip

Reputation: 11317

How can I list all components on a gameobject exclude the Transform and how can I destroy(delete) the components?

public class ComponentsTests : MonoBehaviour
{
    public List<Component> allComponents = new List<Component>();

    // Start is called before the first frame update
    void Start()
    {
        foreach (var component in gameObject.GetComponents<Component>())
        {
            if (component.name != "Transform")
            {
                //allComponents.Add(component);
                Destroy(component);
            }
        }
    }
}

I tried two tests first to add the components to a list. But I want to do it without the Transform.

Then I tried to delete them destroy them. The problem is that two components depend on another one and I can't delete them if I deleted the other one first. Is there a way to find out if any component depend on any other and then destroy them in the right order ?

Upvotes: 1

Views: 511

Answers (1)

Rishaan Gupta
Rishaan Gupta

Reputation: 563

You shouldn't check if a component is a Transform using component.name, as:

Components share the same name with the game object and all attached components.

https://docs.unity3d.com/ScriptReference/Object-name.html

Meaning the name of your transform, won't be "Transform", unless your GameObject is named "Transform", in which case all components on that object will have the name "Transform".

Instead use the is keyword:

if (component is Transform)


Unoptimized Example

Here is an unoptimized example of how you can go about removing all components, the first two functions are taken from this answer.

private bool Requires(Type obj, Type requirement)
{
    //also check for m_Type1 and m_Type2 if required
    return Attribute.IsDefined(obj, typeof(RequireComponent)) &&
           Attribute.GetCustomAttributes(obj, typeof(RequireComponent)).OfType<RequireComponent>()
           .Any(rc => rc.m_Type0.IsAssignableFrom(requirement));
}

bool CanDestroy(Type t)
{
    return !gameObject.GetComponents<Component>().Any(c => Requires(c.GetType(), t));
}

bool TryDestroy(Component c)
{
    if (CanDestroy(c.GetType()))
    {
        Destroy(c);
        return false; // Return false to not include
    }

    return true; // Return true to include
}

// Call This
void TryDestroyAll()
{
    var components = GetComponents<Component>();

    // Components that aren't self or transform
    IEnumerable<Component> comps = components.Where(c => !(c is Transform) && c != this);

    do {
        // Try to destroy every component, any components that aren't destroyed are returned.
        comps = comps.Where(c => TryDestroy(c));
    } while (comps.Count() > 0);
}

Make sure you have these imports:

using System;
using System.Collections.Generic;
using System.Linq;

Upvotes: 1

Related Questions