DarkT
DarkT

Reputation: 179

Is there a more efficient way to disable multiple scripts while keeping some active on a single game object in Unity?

I am trying to turn off all components instead of one of them on a Game Object based off of which number is chosen as the index. The code is longer than this but I am trying to figure out if there is a more efficient way to doing so rather than calling so many GetComponents. When running this code I am getting a StackOverflowException and I think it is because of how many time I am calling GetComponent. The idea that I had was to put each GetComponent into an array and if the index matches the array number than make that component true and make the rest false. I that is the right direction can some help me in the right direction on how I create arrays out of scripts.

switch (index) {
    case 0:
        player.GetComponent<_2dxFX_HSV1>().enabled = false; 
        player.GetComponent<_2dxFX_HSV2>().enabled = false;
        player.GetComponent<_2dxFX_HSV3>().enabled = false; 
        player.GetComponent<_2dxFX_HSV4>().enabled = false; 
        player.GetComponent<_2dxFX_Negative>().enabled = false; 
        player.GetComponent<_2dxFX_Lightning>().enabled = false; 
        player.GetComponent<_2dxFX_MetalFX>().enabled = false; 
        player.GetComponent<_2dxFX_Pixel8bitsC64>().enabled = false; 
        player.GetComponent<_2dxFX_GoldFX>().enabled = false; 
        player.GetComponent<_2dxFX_Waterfall>().enabled = false; 
        player.GetComponent<_2dxFX_Hologram>().enabled = false; 
        player.GetComponent<_2dxFX_PlasmaRainbow>().enabled = false; 

        break;

    case 1:
        player.GetComponent<_2dxFX_HSV1>().enabled = true; 
        player.GetComponent<_2dxFX_HSV2>().enabled = false;
        player.GetComponent<_2dxFX_HSV3>().enabled = false; 
        player.GetComponent<_2dxFX_HSV4>().enabled = false; 
        player.GetComponent<_2dxFX_Negative>().enabled = false; 
        player.GetComponent<_2dxFX_Lightning>().enabled = false; 
        player.GetComponent<_2dxFX_MetalFX>().enabled = false; 
        player.GetComponent<_2dxFX_Pixel8bitsC64>().enabled = false; 
        player.GetComponent<_2dxFX_GoldFX>().enabled = false; 
        player.GetComponent<_2dxFX_Waterfall>().enabled = false; 
        player.GetComponent<_2dxFX_Hologram>().enabled = false; 
        player.GetComponent<_2dxFX_PlasmaRainbow>().enabled = false;  

        break;
    case 2:
        player.GetComponent<_2dxFX_HSV1>().enabled = false; 
        player.GetComponent<_2dxFX_HSV2>().enabled = true;
        player.GetComponent<_2dxFX_HSV3>().enabled = false; 
        player.GetComponent<_2dxFX_HSV4>().enabled = false; 
        player.GetComponent<_2dxFX_Negative>().enabled = false; 
        player.GetComponent<_2dxFX_Lightning>().enabled = false; 
        player.GetComponent<_2dxFX_MetalFX>().enabled = false; 
        player.GetComponent<_2dxFX_Pixel8bitsC64>().enabled = false; 
        player.GetComponent<_2dxFX_GoldFX>().enabled = false; 
        player.GetComponent<_2dxFX_Waterfall>().enabled = false;
        player.GetComponent<_2dxFX_Hologram>().enabled = false; 
        player.GetComponent<_2dxFX_PlasmaRainbow>().enabled = false; 

        break;
    }

Upvotes: 1

Views: 725

Answers (2)

TheSoftwareJedi
TheSoftwareJedi

Reputation: 35196

Perhaps disable all components, then just enable the one you want based on the switch statement?

foreach (var c in player.GetComponents<Component>())
{
    if (c is DontDisable1 ||
            c is DontDisable2)
        continue;
    c.enabled = false;
}

switch (index)
{
    case 1:
        player.GetComponent<_2dxFX_HSV1>().enabled = true;
        break;
    case 2:
        player.GetComponent<_2dxFX_HSV2>().enabled = true;
        break;
}

Upvotes: 1

KYL3R
KYL3R

Reputation: 4073

First of all, the GetComponent<> is quite costly. Don't do it in Update if you can avoid it.

Avoiding means: if these components stay the whole time, you can cache the references:

private List<GameObject>() all_components = new List<GameObject>();

And then, you may add them in Start(), and call GetComponent just once per component:

void Start()
{
    foreach(Component c in transform.children)
    {
        all_components.Add(c);
    }
    // Or even GetComponentsInChildren, where (true) includes the inactive gameobjects!
}

GetComponentsInChildren

Alternatively, only the ones you want:

all_components.Add(GetComponent<_2dxFX_HSV1>());
all_components.Add(GetComponent<_2dxFX_HSV2>());
// and so on... (but in Start - so just once per runtime :))

If you want maximum performance, e.g. even avoid this spike at start, do this:

public Gameobject[] all_components_array;

And in Inspector, drag them all in. You may need to specify the array size first. However, no need to collect them in Start() anymore :)

Now, how to disable/enable?

This disables all:

for(int i = 0; i < all_components.Count; i++)
{
    all_components[i].SetActive(false);
}

If you want to disable "all but 2" - disable all, then enable the 2 you want:

all_components[4].SetActive(true);
all_components[9].SetActive(true);

You could also activate all, then disable some. Depends on what you want in your switch-case you posted.

Upvotes: 2

Related Questions