Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Prefix-casting / as-casting (Instantiating Prefabs and assigning parents)

Discussion in 'Scripting' started by Skeletim, Aug 22, 2013.

  1. Skeletim

    Skeletim

    Joined:
    Jun 19, 2013
    Posts:
    29
    I'm looking for a better understanding of prefix casting vs as-casting especially in reference to Instantiate() prefab objects. I know both are the same, sort of, but not quite, but consider this line of code that I wrote.

    Prefix casting:
    Code (csharp):
    1. Gameobject newObj = (GameObject) Instantiate( Resources.Load("Prefabs/Object") );
    2. newObj.transform.parent = bigObj.transform;
    This actually gave me this error "Setting the parent of a transform which resides in a prefab is disabled to prevent data corruption"

    But, when I used as-casting, I didn't get the error, and the code worked correctly.

    As casting:
    Code (csharp):
    1. Gameobject newObj = Instantiate( Resources.Load("Prefabs/Object") ) as GameObject;
    2. newObj.transform.parent = bigObj.transform;
    I see as-casting as sort of a post-cast. Where the object checks to see if its cast-able after it's ready to assign the value, if it can't then the new variable gets the value null, and the program continues, where as prefex casting checks prior, and if it can't cast, then it doesn't assign and instead throws an exception. This (prefix casting) is probably preferred to prevent problems with data later on, so in long lines of code, you're not stuck with a null value you didn't know how you got.

    What I don't get, is that both instances seem to be able to be cast into a GameObject, therefore why am I allowed to in the latter example, but the exception is thrown in the former example? The problem comes from assigning the parent, not so much instantiating the prefab. What makes one variable "a transform which resides in a prefab" while the other isn't? Is this Unity's way of telling me that this method is not the preferred way to instantiate objects? I can load resources to an object, then instantiate that object, but I'd be creating two instances of that prefab. I didn't really see a need to create two objects every time I want one.
     
    Last edited: Aug 22, 2013
  2. HelloKity1231

    HelloKity1231

    Joined:
    Nov 25, 2012
    Posts:
    121
    The "as-casting" is a safe cast, it will throw exception if something is wrong and will not covert your object.
    The "casting" will convert object event something is wrong.

    Ah, i don't saw it!, you already wrote something like that.
     
    Last edited: Aug 22, 2013
  3. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    This is incorrect. as will return null if the cast fails. An explicit cast (using parenthesis) will throw an exception.

    As to the OP - both instances of that code should work, that's rather odd. Are you absolutely sure you're not trying to set the prefab's transform?
     
  4. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
  5. Skeletim

    Skeletim

    Joined:
    Jun 19, 2013
    Posts:
    29
    I found that odd as well. That was the only code that I had that even referenced a prefab. And upon changing the cast from 'prefix' to 'as' removed the error. Although, I can't replicate the error anymore. When I changed it back to explicit cast it worked. So I am not absolutely sure about anything now.

    With that being said though, how would I change the prefabs transform? (or try to since it won't work) That way I know what I may have done and what not to do in the future.



    I have read that as-casting is much faster if you are sure about the data being correct. I don't know speed comparisons though.
     
  6. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    I believe you have it backwards. An explicit cast should be nominally faster but will throw an exception if you don't do it correctly. An implicit (as) cast will allow you to check the success of the cast.

    Code (csharp):
    1.  
    2. Transform t;
    3.  
    4. GameObject go = (GameObject)t; // throws exception
    5.  
    6. GameObject go = t as GameObject;
    7. // check if cast succeeded
    8. if (go != null)
    9. {
    10.  
    11. }
    12.  
    13. // alternately
    14. if (t is Component)
    15. {
    16.     // this would then be ok because t is some derivative of Component
    17.     // because it passed our test above
    18.     Component c = (Component)t;
    19. }
    20.  
    The last bit is handy to check for interface implementations and such.

    In regards to accidentally changing a prefab - if you tried to just load the resource without the Instantiate wrapper it would fail with the exception you saw previously.
     
    Last edited: Aug 22, 2013
  7. Skeletim

    Skeletim

    Joined:
    Jun 19, 2013
    Posts:
    29
    Here is a site that shows the speed performances.
    http://www.codeproject.com/Articles/8052/Type-casting-impact-over-execution-performance-in

    I guess it is possible that I may have ran the code prior to encapsulating the Load statement inside Instantiate. But I feel sure that I didn't. Perhaps I forgot to save the code until I changed to as-casting.

    On that topic, is it better to use Load outside the Update(), in Awake() and Start(), or does it matter?
     
  8. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
  9. mohit-parihar

    mohit-parihar

    Joined:
    Jun 30, 2014
    Posts:
    9
    hi,
    I work on a game or i am newbie, i create a prefab and it work well, now i will create new gameObject as Plane type and want to attached as child to prefab,

    voidAddTextureRuntime (GameObject gObject,string path){
    Texture2D mytexture=null;
    GameObject prefab = null;
    mytexture=(Texture2D) Resources.LoadAssetAtPath(path,typeof(Texture2D));

    prefab = GameObject.CreatePrimitive(PrimitiveType.Plane);
    prefab.transform.parent = gObject.transform;
    prefab.name="CHINE_CHAR";
    prefab.renderer.material.mainTexture = mytexture;
    prefab.renderer.material.shader = Constant.shader;
    prefab.transform.localScale = Constant.SIZE_CHAR;
    prefab.transform.rotation = Quaternion.Euler (90, 180, 0);
    }

    and its give exception:- Setting the parent of a transform which resides in a prefab is disabled to prevent data corruption.

    please help me asap.