AddComponent from a List of Generic Types

I’m trying to add components from a List.

Here is a very similar situation, except he isn’t grabbing them from a List. Unity how can AddComponent()?

Here is my Code so far, but I really don’t know where to go from this.

It kind of works, it does add a component with no errors, but the component that it adds is blank.

public class LittleComponent : MonoBehaviour {

public List<UnityEngine.Object> specialScripts = new List<UnityEngine.Object>();

public Type GenericSpecialtyScript(int script)
        {
            return specialScripts[script].GetType();
        }

 public void AddComponentToObject(GameObject addToObject)
        {
            GenericSpecialtyScript(0);
            addToObject.AddComponent<GenericSpecialtyScript>();
        }

    }

    public class GenericSpecialtyScript : MonoBehaviour
      
        {

        }
}

And here is how I am testing it. Its just an editor script.

public void TestButton()
        {
            if (GUILayout.Button("Test", GUILayout.Height(30)))
            {
                _LittleComponent.AddComponentToObject(_LittleComponent.gameObject);
            }
        }

That code probably shouldn’t even compile. When you do this:

public void AddComponentToObject(GameObject addToObject)
        {
            GenericSpecialtyScript(0);
            addToObject.AddComponent<GenericSpecialtyScript>();
        }

You’re not actually getting the return value of your method, and you’re not using it later. You need to store the return value of a function in a variable in order to use it. Like so:

public void AddComponentToObject(GameObject addToObject)
        {
            var myType = GenericSpecialtyScript(0);
            addToObject.AddComponent(myType);
        }

That doesn’t work either. I was doing this before…

gameObject.AddComponent(GenericSpecialtyScript(0));

Which is basically same thing, and they produce the same error.

So I switched to the top way, which allowed it to be added, even though its obviously not derived from monobehaviour.
For some reason I think this is going to be a pain to get working…

This is the error.

Can’t add component because ‘MonoScript’ is not derived from Component.
UnityEngine.GameObject:AddComponent(Type)

Right, so you’re trying to make a list where you can drag-and-drop scripts and then add them to objects at runtime.

That won’t work out of the box. Scripts are represented by the type MonoScript, which is an editor-only type. So you could make this work in the editor (by casting the genericSpecialtyScript to MonoScript and using GetClass to get the class. But that’s UnityEditor namespace stuff, so again, won’t work in builds.

This is a very common request, so it should probably be a feature in Unity. You’ll need to do some editor scripting to make it work. I’ll see if I can throw something together.

1 Like

Get it while it’s hot: Runtime Script Field!

Usage:

public class Example : MonoBehaviour
{
    public ScriptReference scriptReference;

    void Start()
    {
        gameObject.AddComponent(scriptReference.script);
    }
}
1 Like

Its actually just for an editor script, no runtime stuff, so this should be perfect. I’ll see if I can get it working properly then report in.

Thank you my man!

Edit: Ok I ran into 2 seemingly simple problems. One with yours and the other with MonoScript.
#1 Where is ScriptReference derived from? Do I make the class, or where is it?

#2 When I reference MonoScript from a script derived from MonoBehaviour there is no GetClass();

Then when I try to use MonoScript instead of MonoBehaviour I get this error.

“cannot derive from sealed type ‘MonoScript’”

ScriptReference is from the repo I linked.

I don’t understand #2. Could you post the code?

Oh ok I only copied the code, I’ll download and try.

And for #2 I was trying to make a new Class derived from MonoScript.

btw you can use

 public MonoBehaviour scriptReference;

 public List<MonoBehaviour> MyScriptList = new List<MonoBehaviour>();

You can only select prefabs though, not Scripts.
And even if you could, running its same issue.

Baste I still haven’t got around to trying yet, had no time today. Will update tomorrow.

Isn’t this a basic reflection thing? Or am I missing something.

I would suggest using strings in the editor, then converting that to the type when you add it.

Hey Baste,
Thank you for that! Works perfectly.
Now I’m just wondering if I could use it in my Editor Tool for the asset store.
This will only be a small feature that’s apart of the tool, totally not the beef of it.

And thanks again!

Mormon, sounds like a neat idea, don’t need it now, but I would still like to learn for later.
Know any tutorials or documentation on something like that?

It’s under the MIT license, so yes. It’s nice if you mention me somewhere in the readme or whatever.

About using strings and converting it through reflection, that’s what my tool does. You give it a type, it converts it to the type’s “assemblyQualifiedName” before serialization, and converts back after.

This means that if the user renames scripts, the reference will be lost. There’s a possible work-around in the editor (only) where you also store the reference to the script asset’s GUID, and try to recover from that if the type can’t be found. It’s a halfway measure, since it won’t work in builds (no script assets)

just head up on using reflection, it will slow down your performance if used in a frame related event.

Awesome thanks a lot, and yes of course I will credit you.

Good to know Max ty, luckily that’s not how I’m using it.