Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

unityscript API change: AddComponent with custom type

Discussion in 'Unity 5 Pre-order Beta' started by mradfo21, Nov 14, 2014.

  1. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    So I get that an api change was made so that:

    gameObject.AddComponent("rigidbody")

    becomes

    gameObject.AddComponent.<rigidbody>();

    cool. however I have an issue and since theres no documentation so i'm asking how i should approach this.

    I have a custom component i'm trying to instantiate (this is a state machine), but it passes in a string, that string is the name of the component to be added.

    var foo:String = "myComponent";
    gameObject.AddComponent.<foo>();


    however, this if course just adds the component "foo" to my object, not "myComponent"

    var foo:System.Type = System.Type.GetType("myComponent")
    gameObject.AddComponent.<foo>();


    this doesn't work either, claiming:

    The name 'foo' does not denote a valid type ('not found').

    so after these api changes.. how are you supposed to dynamically add components from variables? The ease of doing this is one of the things i really appreciated about UnityScript.
     
  2. AdrianoVerona_Unity

    AdrianoVerona_Unity

    Unity Technologies

    Joined:
    Apr 11, 2013
    Posts:
    317
    Hi

    The best option is do use the typeof operator:

    gameObject.AddComponent(typeof(TheTypeOfTheComponent));

    but that only works if the type in question is defined in the same language as the caller (meaning, it is defined in the same assembly as the caller), or in a plugin or an imported assembly.

    if you do need to use a type name (instead of a type reference), then you can do something like:

    gameObject.AddComponent(System.Type.GetType("fully qualified type name"));

    The "fully qualified type name" is the full name of the type, including assembly and namespace (http://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx) (if the type is defined in the same assembly then the namespace qualified name is enough).

    But keep in mind that Type.GetType(string) may not be supported in all platforms.

    Best

    Adriano
     
    Vazili_KZ, martinell and shkar-noori like this.
  3. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    so after having tested this trying to figure out the problem, it seems System.Type.GetType(a string variable) does not return the correct type. or atleast it doesn't behave like one would desire.

    if I enter the type (camAim) as the type (there is a component called camAim), and call:

    var state:String = "camAim"
    typeof(System.Type.GetType(state)))


    i get "System.MonoType"

    but shouldn't this instead be of type camAim? or System.MonoType.camAim ?

    because right now, if i call this code in the game:

    state = "camA

    currentState = state;
    currentStateObj = gameObject.AddComponent(typeof(state));
    currentStateObj.Enter();


    the game will lock up and i have to force quit to close. Ive submitted a bug report and they said "seems like an infinite loop". which is odd.. as there is nothing like that in my code. if i comment out

    currentStateObj = gameObject.AddComponent(typeof(state));

    then the game does not crash and runs just fine. The crash is clearly related to the AddComponent function
     
  4. AdrianoVerona_Unity

    AdrianoVerona_Unity

    Unity Technologies

    Joined:
    Apr 11, 2013
    Posts:
    317
    That is definitely correct, System.GetType() will return an instance of a class that inherits from System.Type (in this case System.MonoType).

    if you do:

    Code (JavaScript):
    1. Debug.Log(System.Type.GetType("camAim").Name);
    then you should get back the "camAim"

    What is the issue # ? I'll take a look on Monday

    Adriano
     
  5. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    hey Vagaus,

    case number: 648845
    http://fogbugz.unity3d.com/default.asp?648845_durj6fcf16vjguf0

    i just checked and they marked it as closed for some reason. DEFINITELY not closed. I just replied to the QA guy with a simplified scene, but now im not sure if they'll even get it with the case closed.

    i'm sending the package here.

    just press "spacebar" and it will lock up the game / editor and you'll have to force quit. beware. It is the simplest repro case of this bug.

    its ground my development to a hault. really hope you see it on your end.
     

    Attached Files:

  6. AdrianoVerona_Unity

    AdrianoVerona_Unity

    Unity Technologies

    Joined:
    Apr 11, 2013
    Posts:
    317
    Hi.


    The issue is open again but it is marked as "pending information". Are you talking to someone at Unity?

    Anyway, I'll try to give it a try latter today.
     
  7. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    i replied to your email. Thanks for taking a look at this. i still think something is wrong at a low level. let me know if you didn't get it

    Matt R
     
  8. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    Still trying to get this resolved. SO close now.

    Just to update the community, in Unity Script if you want to get the type of a component, this is the syntax

    // WRONG
    gameObject.AddComponent(System.Type.GetType("Rigidbody"));

    // RIGHT
    gameObject.AddComponent(System.Type.GetType("UnityEngine.Rigidbody, UnityEngine")); // right type name used

    unfortunately you can still not add custom components through a string

    var state:String = "actionNuetral";
    gameObject.AddComponent(System.Type.GetType("UnityEngine."+state+", UnityEngine")); // right type name used

    will unfortunately return Null still.

    I will keep posting while trying to resolve this.
     
  9. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    Instead of GetType try typeof and don't use a String:

    Code (csharp):
    1.  
    2. gameObject.AddComponent(typeof(Rigidbody));
    3.  
    Or a better question... why resolve the type at all if you already know what it is? If you already know you need Rigidbody for example... why convert that to a string? Since you're using UnityScript, just do:

    Code (csharp):
    1.  
    2. gameObject.AddComponent.<Rigidbody>();
    3.  
    Unless I'm missing something... there's no need to convert to a string. So let's say you have a monobehavior with a type of myComponent... don't use the string, just do:

    Code (csharp):
    1.  
    2. gameObject.AddComponent.<myComponent>();
    3.  
    If myComponent is a variable that references a component from another object, and you want to add it to your current object then do:

    Code (csharp):
    1.  
    2. gameObject.AddComponent(typeof(myComponent));
    3.  
     
  10. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    thanks for the reply. the entire problem is that the types im trying to add come in as strings.

    i should add. this is really a Unity 5 issue. Theres some mysterious syntax for casting strings into types that no one at Unity seems to know after the API change.

    after 10 emails back and forth, no one seems to be able to understand that I, matt radford, have a need to cast strings to types.

    var state = "actionAim" (actionAim is a component)
    gameObject.AddComponent(state) (this is how this worked in 4.6 and below)

    now.. there seems to be no way to do this. The general response is people seem to be very confused WHY im doing this. which is fine. when this project was started I didn't know as much about Unity as i do now and the state machine implementation was created this way. it is now the backbone of my game for better and worse (it actually works really well! ).

    So i do know that there are better ways to add components, but this is the way I NEED to add them. And since this worked in Unity 4.X when the API change was never announced I made that decision and I do plan on sticking with it. My worse case scenario is never getting to use Unity 5 and sticking with 4.6

    I'm grateful for Unity and their support team. They are very helpful. But I am a bit frustrated at this point as every damn email seems to be from a new person who has not read any of the previous emails to do with the case. So every time its this back and forth about "Well don't cast them as strings, reference the type directly". And I get it. It wasn't the best way to do it. But at this point i'm just looking for an answer of "this is no longer supported" or "oh yeah.. its weird that doesn't work"

    I'm pretty sure in the end its going to be something really really simple and i'll laugh it off.

    sorry to vent a little. I really do appreciate the community and Unity's dev / QA team.
     
    Last edited: Dec 10, 2014
  11. AdrianoVerona_Unity

    AdrianoVerona_Unity

    Unity Technologies

    Joined:
    Apr 11, 2013
    Posts:
    317
    This is not UnityScript specific; in any DotNet language, in order to get a "Type" object from a string, you need the full type name (in most cases).

    Also, just to be clear, (as pointed by the other poster) if possible, it is far better to either use the generic version or the one that expected a System.Type.

    Code (CSharp):
    1. gameObject.AddComponent.<Rigidbody>();
    2.  
    3. // or
    4.  
    5. gameObject.AddComponent(typeof(Rigidbody));
    That's expected. Unity do not have a type named "actionNuetral" (as far as I can tell this is a type in your project)

    Have you tried doing something like:

    Code (JavaScript):
    1. var state = "actionNeutral";
    2. gameObject.AddComponent(System.Type.GetType(state));
    (I think this should work)

    Although, based on a quick look on your project code it may be possible to use Type References instead (which should be a little bit faster than using strings and also makes it easier to find typos)

    Code (JavaScript):
    1. var stateType = typeof(actionNeutral);
    2. gameObject.AddComponent(stateType);
    Best

    Adriano
     
  12. mradfo21

    mradfo21

    Joined:
    May 16, 2013
    Posts:
    194
    yeah, originally when i submitted the ticket I had found that

    1. var state = "actionNeutral";
    2. gameObject.AddComponent(System.Type.GetType(state));
    does work. however, it seems to work only once, when the game first starts up, then at runtime whenever you try to perform this operation Unity goes into an inifinite loop. You were able to repro this from the simple example scene i prepared.

    did you find out why

    var state = "actionNuetral"
    print(System.Type.GetType(state)) will always return null ?


    because i think thats where the infinite loop seems to come from
    the game searches over and over for "null" somehow..