Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by donka · May 01, 2014 at 06:39 AM · c#parent-child

Combining prefabs into one game object before calling Instantiation

I want to write a class that puts a bunch of GameObject prefabs (walls, floors, windows, furniture, etc) into a random house-shaped Game Object and return that object to the caller. Once the caller has this single GameObject, it can Instantiate() it into being.

I know I can use this code:

 SomeHousePiece.transform.parent = ParentObject.transform;

to join objects together, but since I'm trying to put this all together BEFORE Instantiation, I get this error:

 Setting the parent of a transform which resides in a prefab is disabled to prevent data corruption.

I've read that this is because I need to call Instantiate() on all these components before I can group them under a single parent, but I really want to avoid calling Instantiate() in the House builder class. I want that class to be purely a thing that generates a Game Object for later use.

Is this possible? I have an impression that I'm fighting against the "Unity way" of doing things, but as a long-time C# developer, there are habits (like separating construction logic from display logic) that are hard to break.

Should I just call Instantiate() from within my Builder class and be done with it?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Owen-Reynolds · May 01, 2014 at 05:00 PM

I prefer keeping prefabs as invariants, so even if you could change the parent, it seems like a bad idea.

One thing you could do is create fake prefabs. Instantiate will gladly copy prefabs or existing gameObjects. So HouseMaker could Instantiate, position, child... everything, but into an object at -999 set to inactive. Then could return that as the "prefab." And, to repeat, later code will gladly Instantiate that.

Or, a more programmery way, and more what you're asking for, have the HouseMaker create and return a HouseBlueprint, which would be used to Instantiate the house. Your main program will never call Instantiate. Instead, it will call Transform H1 = housePattern1.spawn();

HouseBlueprint might look something like:

 class HouseBlueprint {
   Transform myPrefab;
   Vector3 myLocalPos, myLocalRotation, myLocalScale;
   HouseBluePrint[] Children;

   // recursively instantiates, hooks up, positions all PFs that make me: 
   Transform spawn() { return _spawn(null); }

   Transform _spawn(Transform myParent) {
     Transform T = Instantiate(myPrefab, 0 ,0);
     if(myParent!=null) {
       T.parent = myParent;
       T.localPosition = ...
     }
     ...
     foreach(HouseBlueprint b2 in Children)
       _spawn(b2, T);
     return T;
   }

Can think of it as a standard recursive data structure, with an eval() function. The root should probably always be a "positioning" empty, which also solves the problem deciding the parent if you just have 4 walls. I use this trick -- I think it really is the correct solution, but it is very Computer Sciencey.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image donka · May 01, 2014 at 06:56 PM 0
Share

Okay, that's kind of what I was thinking I might have to do (Instantiate fully, but off-screen. The caller handles moving the object into frame). It still doesn't feel right, but I guess it's analogous to calling "new Object()" -- in code, "new" makes stuff appear in memory, in Unity Instantiate() makes stuff appear in the game world.

A few follow-up questions: 1. Is there a reason to return a Transform rather than a GameObject? Is this just good practice? 2. What's the cleanest way to give a class access to the Initiate() method? I'd rather not have RoomBuilder extend $$anonymous$$onoBehaviour since I don't consider it a behavior and it already extends an abstract class. Do I then store an instance of $$anonymous$$onoBehaviour in the builder?

avatar image Owen-Reynolds · May 01, 2014 at 08:18 PM 0
Share

Well, the first idea, I'm assu$$anonymous$$g you want to build "funnyRedHouse" then make arbitrarily many copies. So there are two Instantiates. One is done once, ever, to setup funnyRedHouse, making a fake offscreen prefab. The then the caller can Instantiate that exactly as if it was a real prefab. The caller can treat everything as normal prefabs, nice and clean.

I just prefer to throw around Transforms, and prefer writing T.position to GO.transform.position. Any class can Instantiate (need GameObject.Instantiate for non-$$anonymous$$onoB's?) The tricky part is getting links to prefabs. Seems best to make a monobehaviour "holder" class, on an empty, just to keep all the prefabs, materials, user-set constants... , which might be what you're suggestion.

avatar image donka · May 02, 2014 at 02:50 PM 0
Share

Oh, I see. So the house just sits off screen and serves as a template for further creation. $$anonymous$$akes sense.

I, too, am irritated by writing GO.transform.position, but when I'm designing classes, I can't help but feel like I should have access to the whole GO. I guess that's what transform.gameObject is for?

GameObject.Instantiate() syntax is exactly what I needed. For some reason I couldn't find a statically available Instantiate() method; the only way I'd found was to extend $$anonymous$$onoB.

So, just for the sake of completeness, you would say there is not a way to join together multiple game objects prior to any Instantiate() calls? At least, none that you know of?

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

Get child tag from parent-child collision 1 Answer

An OS design issue: File types associated with their appropriate programs 1 Answer

Enabling/Deactivating objects using keys. 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges