The generic parameter has to be a compile-time Type. This means that you cannot put a variable in there. This is a hard restriction on C#, so no getting around it.
For Unity, you can use the non-generic version of AddComponent, which takes a type variable as a parameter. In your case, you’d use it like this:
Okay, there’s a work-around where you use another method’s parameter to do this, but I find it somewhat awkward. Note that the AddOneScript method needs to take a parameter that it never uses:
public Component[] myScripts;
void AddAllScripts()
{
foreach (var item in myScripts)
{
AddOneScript(item);
}
}
void AddOneScript<T>(T scriptType) where T : Component
{
gameObject.AddComponent<T>();
}
I’m using Component since AddComponent needs the variables it takes to be a Component, not a UnityEngine.Object (or System.Object). I haven’t tested it, and it’s kinda messy, but it’ll probably work, if you really feel like you want to do that.
thank you Baste,get a little problem,that if i change Object to Component,i can’t drag script to Component slot in Editor,Object type can.what shall i do?
it seems the script type is MonoScript,not Component.
when using AddComponent if i direct write the script name,i dont’ know why they just turn to be Component type automatically.
MonoScript is a weird beast. First of all, it only exists at editor time, which makes sense, as the scripts themselves are not included in a build (only the compiled code is). This means that drag-and-dropping a script component into a list, and then adding scripts from that list to object won’t work in runtime.
If you’re doing this stuff editor time, you could use a list of MonoScripts, and do the same thing as I posted, just substituting this call:
AddOneScript(item);
with this:
AddOneScript(item.GetClass());
Assuming that item is a MonoScript. GetClass() gives you the type of the script the MonoScript defines.
The type System.Type' must be convertible to UnityEngine.Component’ in order to use it as parameter T' in the generic type or method MainScript.AddOneScript(T)’
public MonoScript[] allScripts;
void Start()
{
foreach (var item in allScripts)
{
AddOneScript(item.GetClass());
}
}
void AddOneScript<T>(T scriptType) where T : Component
{
gameObject.AddComponent<T>();
}
does it mean there is no way to convert MonoScript to Component type
tried chage array to list
public List<MonoScript> allScripts;
same error.
ok,maybe i should ask is there a way to compile script to Component at run time?
i don’t know c# too much,but i heard c# can compile script at run time.
say there is a class script saved as string,and this string can be compiled to be instance.
is that true?if it is.can i use this to compile it to Component?But it seems i still don’t know how to convert it to be Component type
This means that not all MonoScripts you add are able to be used with AddComponent. Some may be, some may not, compiler does not know that. That is why the “where T : Component” is introduced. This tells the compiler that you are only going to give Component types to that function.
You could try (I have not tested this, since i am at work and do not have Unity here)
void Start() {
foreach (var item in allScripts) {
if (item is Component) {
AddOneScript(item.GetType()); // may have to cast item to Component using "Component(item).GetType()"
}
}
}
Note again that this won’t work in a build, as the UnityEditor namespace (that contains MonoScript) does not exist there.
Look, what you’re trying to do isn’t really viable. Compiling at runtime is also a bad idea - it’s slow, it’s a lot of work, and it won’t work on a lot of platforms as they don’t allow that stuff (IOS is an example).
You’re probably trying to solve a specific issue - if you post that, we can try to find a better solution than what you’re trying to do.
Thank you so much for this!! My problem is that my function similar to AddComponents() had been working with various types of components but when I tried to send it a SphereCollider, it would exit without letting me debug it, and create a unity [Debug Updater] object in the hierarchy as a result.
By adding the “where” to the signature, it suddenly started working with SphereCollider too. Thank you!