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

A question about Instantiate

Discussion in 'Scripting' started by winterFirst, Dec 21, 2014.

  1. winterFirst

    winterFirst

    Joined:
    May 30, 2014
    Posts:
    2
    I was following the 'Scripting' video Tutorials (great job by the way :)), and could not wrap my head around the Instantiate method usage (I cross-checked the documentation, and it confirms what has been shown in the video).
    Both the video and the documentation use the 'as' operator to cast the object instance returned by Instantiate to a RigidBody instance.
    I understand that casting to a RigidBody instance allows the code to access the properties and methods pertaining to such class (for example, the velocity property).
    What I don't understand is: how can a GameObject instance (for example the projectile in the video tutorial) be cast to a RigidBody instance ?
    In other words, what is the relationship between a GameObject and its RigidBody component ?
    I always cast 'along' an inheritance scheme, but the GameObject/Component seems more like a 'has a' relationship rather than a 'is a' one.
    Any help, appreciated!
     
  2. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You have some misunderstanding here. You can't cast between a component and a game object.

    Instantiate is a slightly strange method in that no matter what you send it returns a object. The object is the same type as the object passed in as the first argument. But you have to cast it to do anything useful. (Note to any Unity devs, a generic version of Instantiate would be nice!).

    Here are some code examples

    Code (CSharp):
    1. // This will return a GameObject
    2. GameObject myPrefab;
    3. GameObject clone =(GameObject) Instantiate (myPrefab);
    4.  
    5. // This will return a RigidBody
    6. RididBogy myPrefabRigidBody;
    7. RigidBody clone = (RigidBody) Instantiate (myPrefabRigidBody);
    8.  
    9. // This will not work, casting a RigidBody to a GameObject
    10. RigidBody myPrefabRigidBody;
    11. GameObject clone = (GameObject) Instantiate (myRigidBodyPrefab);
     
    BenZed and winterFirst like this.
  3. winterFirst

    winterFirst

    Joined:
    May 30, 2014
    Posts:
    2
    Many thanks BoredMormon !
    I might add that, reviewing the video about the Instantiate method (http://unity3d.com/learn/tutorials/modules/beginner/scripting/instantiate) at 1:44, I noticed that the references passed to the public instances declared by the UsingInstantiate script, are not simply Rocket and RocketPlace, but Rocket (RigidBody) and RocketPlace (Transform): this way the editor seems to infer which Component of the GameObject is compatible with the type required by the script.
     
  4. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    It helps to imagine the "as" keyword to mean "promote" or "demote" rather than "cast"

    Casting requires explicit or implicit methods to covert one type to another.

    Promoting / Demoting allows you to change the runtime type of an object to one of it's base or derived classes.

    In the case of Instantiate, it returns a UnityEngine.Object, which is the base class for all objects unity works with.

    Now, you cant cast a gameObject to a rigidBody, but FROM UnityEngine.Object, you can "promote" to either.

    Edit: code example because the syntax I was thinking is different from BoredMormon

    Code (CSharp):
    1. //Promote
    2. var rigidBody = Instantiate(prefab) as RigidBody;
    3.  
    4. //Demote
    5. var obj = rigidBody as UnityEngine.Object;
    6.  
    7. //unsupported cast, returns null
    8. var gameObject = rigidBody as GameObject;
     
    Last edited: Dec 21, 2014
    winterFirst likes this.
  5. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Since we are on the topic of casting, the key difference between casting as I showed it and casting as @BenZed showed it is the response to impossible casts. My version will fail with an error as soon as the cast is attempted (unsafe). Using the as key word will return null if the casting is not possible, hence using as is referred to as 'safe' casting.

    There are advantages and disadvantages to both. Unsafe casting is slightly faster. Safe casting is better if you are not totally sure if the cast can be done.

    Note all of this applies to C#. JavaScript behaves differently.
     
    winterFirst likes this.
  6. Zerot

    Zerot

    Joined:
    Jul 13, 2011
    Posts:
    135
    Just to add on to the discussion about the casts:

    You should almost always use the (type) style casts because almost all of the time you know the exact type it should be and it should be an error if it is a different type. e.g. with Instantiate you know exactly what type you put in and gets returned so you should use an (type) cast. The reason for this is that you will want an error as soon as possible. With an "as" cast it will return null and you will either need to explicitly check for that or end up with a null reference exception at a later point. But with a () cast you will get an exception the moment the casting fails.

    The "as type" cast is only useful when you are not sure about the actual type. In other languages you would first do a type check before casting which will do a type cast/check twice(once when checking and once when casting), but with "as type" it only needs to do the check/cast once.

    e.g.
    Code (csharp):
    1. if (obj is Type) // <-- typecheck here
    2. {
    3.     Type t = (Type)obj; // <-- typecheck here
    4. }
    vs

    Code (csharp):
    1. Type t = obj as Type; // <-- typecheck here
    2. if (t != null)
    3. {
    4. }
     
    Kiwasi, BenZed and winterFirst like this.
  7. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    There you go! I've been doing it inefficiently, all this time!

    Thats a practice i'm going to adopt.
     
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Fail fast is definely a good reason for () casting. If there is a problem with your code it's nice to know about it early.