Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Add a custom component by searching for it's name

Discussion in 'Scripting' started by PandawanFr, May 3, 2015.

  1. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Hello,

    I have created a small modding system and I want players to be able to add custom components to a certain object. I already know how to check which object to modify and everything but I have a small problem, this modding system uses strings. And AddComponent only works with Scripts. I could limit mods to have a certain name for their scripts, but what if they want multiple scripts. That's why I need the AddComponent to use the one with the name said in the string.

    My question is: is there a way to AddComponent<CUSTOMSCRIPTNAMEHERE-STRING>()

    Note: I'm doing it in C#.

    I hope I was clear enough, if you don't understand something, ask me and I'll try to explain it better.

    Thank you!
     
  2. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    Code (csharp):
    1.  
    2.     void Start () {
    3.         //We have a string holding a script name
    4.         String ScriptName = "YourScriptNameWithoutExtension";
    5.         //We need to fetch the Type
    6.         System.Type MyScriptType = System.Type.GetType (ScriptName + ",Assembly-CSharp");
    7.         //Now that we have the Type we can use it to Add Component
    8.         gameObject.AddComponent (MyScriptType);
    9.     }
    10.  
     
    Last edited: May 3, 2015
    Fajlworks likes this.
  3. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Thank you!
    But how would I do it so that it would loads a script from a certain path?
    Because I want it to be custom, I need to add the Application.dataPath, should I add it right here?

    Code (CSharp):
    1. string path = Application.dataPath;
    2. System.Type MyScriptType = System.Type.GetType (path + ScriptName + ",Assembly-CSharp");

    EDIT:
    I tried your code and it doesn't work, I get this error:
    AddComponent asking for invalid type
    UnityEngine.GameObject:AddComponent(Type)
     
    Last edited: May 4, 2015
  4. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353
    gameObject.AddComponent<MyScriptType>();
     
  5. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
  6. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353
    Didn't even notice that. Oh yeah, that's a whole other bag of cats now. I have no experience with anything like that. I might take a look at those links myself. Good luck @Mig35700 !
     
  7. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Thanks! I kinda want players to be able to add custom scripts that are not referenced in Unity and reference them at runtime...

    I have searched all around google, and don't really get how I could do it.
     
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Reflection plus asset bundles.

    Asset bundles let you create assemblies that Unity games can load at runtime.

    Reflection lets you examine assemblies at runtime.

    Be warned, this is a deep rabbit hole to start down.
     
    hamsterbytedev likes this.
  9. hamsterbytedev

    hamsterbytedev

    Joined:
    Dec 9, 2014
    Posts:
    353
    What a wonderful use of simile haha
     
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Lol. Totally accidental.:oops:
     
  11. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    I thought asset bundles could not contain scripts...
     
  12. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
  13. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Ok, well thing is I already have a big system so I just want to know if there is a way to do it without assets bundles or anything of the sort. I am using a txt file for the mod itself, and using a "Parser" which will get each lines and separate them into words. And then I test for the right word and do some stuff. I wanted it to go like that "cube addComponent NAMEOFCOMPONENT."

    So if you know a way to do it without redoing everything, then you can tell me, if you don't know, then I'll just try to make a super advanced system (maybe so advanced that it will become it's own programming language)
     
  14. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Implementing a run time language is not that uncommon. LUA is a popular one I see bandied about. Never tried it myself.
     
  15. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    It's still not clear whether the components you're talking about (NAMEOFCOMPONENT above) are scripts provided by the mod, or scripts already in your game, and the mod merely adds them.

    In the former case, yeah, it's a deep rabbit hole indeed. You might be better off embedding Lua (which is fairly easy).

    In the latter case, it's not so bad. In Unity 4 and earlier, you could just call AddComponent with the name of the component. Unity 5 has deprecated that, and it changed my code to this:

    Code (Csharp):
    1.   CityPartpart = UnityEngineInternal.APIUpdaterRuntimeServices.AddComponent(noob, "Assets/Scripts/CityParts/CityPart.cs (33,19)", className) asCityPart;
    ...which is ugly and generates a warning in the editor, but it works. It's on my to-do list to find a cleaner method... I suspect that @NA-RA-KU's technique above is the way to do it.
     
  16. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Ok, well, I'll see later for custom scripts, but do you know a way for script that already exist?

    Also, Joe, what type should the variable be?

    EDIT: I did that: modifiedObj.AddComponent(param[3]); and Unity requested an API update for this script, so I let it update and I'l see if this works:
    UnityEngineInternal.APIUpdaterRuntimeServices.AddComponent(modifiedObj, "Assets/Files/Script/Mods/ModParser.cs (151,5)", param[3]);


    EDIT 2: Ok that works, now let's see if it works with custom scripts...
     
    Last edited: May 6, 2015
  17. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    YUUSS! It works, Unity tells me to update it too but it works so I'm not going to.

    Thanks everyone!
     
    JoeStrout likes this.
  18. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Ok, now I just want to know if there is a way to do the same but for other type of resources? If not then that's fine. I just wanted to know.
     
  19. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Other type of resources? Like what?
     
  20. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Like Textures... Prefabs...


    EDIT: I found out that because the code you gave me is obsolete (even though it works), I can't compile/build the game. I have to remove/comment the line.
    I thought @NA-RA-KU's technique would work, but I get a weird error/warning message.
    "AddComponent asking for invalid type
    UnityEngine.GameObject:AddComponent(Type)"
     
    Last edited: May 10, 2015
  21. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Ok, I decided to move the mods folder to the resources folder to be able to use the current system that I have and Resource.Load. But I wonder if there is a way to Resource.Load a script...
     
  22. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    What were you trying to add?
     
  23. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Well, I did just what you gave me. In your script at the very beginning of this thread.
     
  24. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    So you were trying to load a script, and not something else?
    And you removed the .cs extension?

    Did it work in the editor but not the build? Or did it not even work in the editor?
     
    Last edited: May 15, 2015
  25. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Your script doesn't work in the Extension. (That's the error about this one UnityEngine.GameObject:AddComponent(Type))

    and @JoeStrout 's doesn't work in build mode.
     
  26. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    Works for me.
    Works in editor and works in builds. I just tested it.

    I have a script that is in the project but is not included in the scene. I fetch it's type from a string, I add it as a component to a game object, and then it prints on screen that it's alive.

    Code (csharp):
    1. String ScriptName ="ModParser";
    No path. No file extension.
     
  27. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    And you are doing it like that right?

    Code (CSharp):
    1.         //We need to fetch the Type
    2.         System.Type MyScriptType = System.Type.GetType (ScriptName + ",Assembly-CSharp");
    3.         //Now that we have the Type we can use it to Add Component
    4.         gameObject.AddComponent (MyScriptType);

    Also, does it matter if it's a string instead of a String ?
     
  28. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Yup, I still get this:

    AddComponent asking for invalid type
    UnityEngine.GameObject:AddComponent(Type)


    Note: I tried doing it with Rigidbody like that
    modify Test addComponent Rigidbody
    (Where Test is the name of the object)
     
  29. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    Rigidbody is not one of your c# scripts.

    I asked you explicitly
    Code (csharp):
    1.  
    2.         String UniType = "UnityEngine.Rigidbody";
    3.         System.Type UnityType = System.Type.GetType (UniType + ", UnityEngine");
    4.         gameObject.AddComponent (UnityType);
    5.  
     
  30. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    OOOOOOH! Ok, I get it! So for custom scripts, i don't put anything, and for Unity scripts, I put UnityEngine. before the name.
     
  31. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    Ok, It works! THANK YOU SO MUCH! :)
     
  32. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    That is one difference, the other difference is that your scripts are under the "Assembly-CSharp" assembly, and Unity stuff is under the "UnityEngine" assembly.

    If you don't know whether it is a custom script or a unity type for some reason, or you don't want to use any prefixes, then you can search the assemblies for the type, although it's slower.

    See LordOfDuct's function

    http://forum.unity3d.com/threads/addcomponent-string-still-needed.317042/
     
  33. PandawanFr

    PandawanFr

    Joined:
    Nov 27, 2013
    Posts:
    68
    One last question, if I want to allow JavaScript and C#, I already mad the way to differentiate, but what's the type? Is it
    ", Assembly-JavaScript" ?

    EDIT: Nvm, I used the script in the link that you gave me, which is really cool as it searches through the whole project. And it works with any type of script! Again, thank you!!!!
     
    Last edited: May 16, 2015
  34. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    I *think* it's "Assembly-UnityScript"