• 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 tpainton · Nov 01, 2015 at 03:43 PM · scripting problem

Another, "Setting the parent of a transform which resides in a prefab" problem.

I have a gameObject which holds two scripts, HackManager and TextBehavior.

I use the TextBehavior class on many objects as it is my tool to display text in a multitude of situations. I just attach TextBehavior to different gameObjects and then use its methods.

HackManager generates a list of objects that are hacking targets the passes that to the TextBehavior class for processing and display.

 private void DisplayScanResults (List<HackingTarget> targets) {
         textBehavior = (TextBehavior) GetComponent<TextBehavior> ();
         textBehavior.DisplayDown (targets, TextBehavior.topLeft);
     }

The TextBehavior class/script then displays the results for me as such..

 // Displays a list of HackingTargets in column starting at origin. 
     public void DisplayDown (List<HackingTarget> targets, Vector3 origin) {
 
         foreach (HackingTarget target in targets) {
             GameObject entry = (GameObject)Instantiate (textMesh, origin, Quaternion.identity);
             // Add the appropriate listener script.  
             entry.AddComponent<ScanClickLink> ();
             ScanClickLink clickscript = entry.GetComponent<ScanClickLink> ();
             clickscript.Target = target;
             entry.transform.parent = gameObject.transform;  // THIS IS WHERE THE ERROR OCCURS
             entry.transform.localPosition = origin;
             TextMeshPro tMesh = entry.GetComponent <TextMeshPro> ();
             tMesh.text = BuildTargetDesc (target);
             tMesh.ForceMeshUpdate ();
             float newY = tMesh.mesh.bounds.center.y + tMesh.mesh.bounds.size.y + .2f;
             Vector3 temp = new Vector3 (0, newY, 0);
             origin -= temp;
         }
     }

I attach an additional script to each textmesh which handles additional interface from user. Then parent the textMeshes to the gameObject which holds the mentioned scripts. This is where the problem crops up. The commented line throws, "Setting the parent of a transform which resides in a prefab is disabled to prevent data corruption".

I should also add, this technique worked great for months until I migrated the game code to a new laptop. That SEEMS to be when this problem cropped up. I may be mistaken though. The error may have been introduced somewhere else.

Comment
Add comment · Show 3
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 Glurth · Nov 01, 2015 at 04:46 PM 0
Share

You quite clearly instantiate the prefab into a GameObject "entry" on line 5: I would not expect this error either! I assume "text$$anonymous$$esh" in line 5 is a reference to the preFab to be instantiated?

avatar image tpainton Glurth · Nov 01, 2015 at 05:30 PM 0
Share

Yes, text$$anonymous$$esh is a public variable that is populated in the editor window by the prefab that I dragged in.

 public GameObject text$$anonymous$$esh;

Yea, baffling.

avatar image Pharan · Nov 02, 2015 at 02:45 PM 0
Share

I thought it might be useful to note:

These lines:

      entry.AddComponent<ScanClickLink> ();
      ScanClickLink clickscript = entry.GetComponent<ScanClickLink> ();

can be simply implemented as

 ScanClickLink clickscript = entry.AddComponent<ScanClickLink>();

In other words, AddComponent actually returns the component it adds. The other reason to do this is that the GetComponent method can be pretty heavy if you do it enough times, and given the right conditions.

3 Replies

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

Answer by Pharan · Nov 02, 2015 at 02:53 PM

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

I tried a few cases of this and here are the situations I found where it logs that error:

(1) Script is in an instantiated GameObject. Target child is a prefab. (2) Script is in a prefab. Target child is instantiated. (3) Both are prefabs.

Obviously, there's no error when both are instantiated. It works in that case.

It may be helpful to note that at runtime, all instantiated prefabs (according to some Unity talks I watched) are supposed to have no knowledge of themselves coming from prefabs.

May we see where you are getting your List<HackingTarget> elements?

Comment
Add comment · Show 2 · 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 tpainton · Nov 02, 2015 at 07:14 PM 0
Share

Okay. I figured it out. I recently switched to the GUI buttons for ease of use in my game. The GUI buttons have the OnClick() function. When I click my button, IT calls the prefab method, Notice, I have dragged in the Hack$$anonymous$$anager as the object.. So while the Hack$$anonymous$$anager in the game is instantiated, the button is calling the prefab method which subsequently calls the prefab method StartScanning which propagates the error to the scripts originally posted.

alt text

 // Commence scanning.
     public void StartScanning () {
         List<HackingTarget> targets = ScanForTargets (GameControl.control.netPath.GetCurrentNetwork());
         DisplayScanResults (targets);
         Destroy (GameControl.control.iScanButton);
     }

The problem then is..

How do I call a method on an instantiated object from the OnClick () method on the GUI button??? I guess there might be a way to grab the component, and then set the target object? I don't even know what the gameObject variable is called.

avatar image tpainton tpainton · Nov 02, 2015 at 07:20 PM 0
Share

thinking about this.. I guess I could have StartScanning() simply find the prefab by tag, and then call DisplayScanResults() on the prefab... THAT should work.. OR really more properly, have the OnCLick call something like StartScanningOnHackInstance(), this simply gets the Hack$$anonymous$$anager instance, then calls StartScanning() on it.. Seems a little awkward.. but..

Another option is a delegate.

avatar image
0

Answer by DblTap · Jul 18, 2016 at 02:25 PM

@tpainton and anyone else who runs into this issue

So I ran into this issue as well, here's what i found was the culprit...

In my particular case I have a GameManager that is an instantiated singleton and in a Menu's OnClick event I call the SwapLevel function in GameManager. After a lot of playing around, reading this and other threads like it, what I've found is this... because the OnClick event procs a call to GameManager.SwapLevel and not GameManager.instance.SwapLevel I had to change the code in SwapLevel to make everything in it refer to the instance, otherwise its all considered the prefab...

So the code

 void SwapLevel(int level)
     {
         if (level >= LevelStuff.Length || level < 0)
             return;
 
         if (transform.childCount > 0)
             foreach (Transform t in transform)
                 Destroy(t.gameObject);
 
         GameObject go = Instantiate(LevelStuff[level]) as GameObject;
         go.transform.SetParent(transform);
         curLevel = level;
     }

Became

 void SwapLevel(int level)
     {
         if (level >= GameManager.instance.LevelStuff.Length || level < 0)
             return;
 
         if (GameManager.instance.transform.childCount > 0)
             foreach (Transform t in GameManager.instance.transform)
                 Destroy(t.gameObject);
 
         GameObject go = Instantiate(GameManager.instance.LevelStuff[level]) as GameObject;
         go.transform.SetParent(GameManager.instance.transform);
         curLevel = level;
     }

Hope this helps!

Comment
Add comment · 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
0

Answer by Bunny83 · Nov 02, 2015 at 03:34 AM

Well, as i already mentioned on that other question you most likely execute this method on a prefab. It would help to see the call stack of your error. From where and how do you call "DisplayScanResults"?

I guess that the gameobject with your "HackManager" is actually a prefab and you execute your methods on the prefab instance.

You make the textMesh instance a child of the gameobject this script is attached to. Since the textMesh clearly is an instance in the scene the only logical reason for this error is that the gameobject you want to use as parent is actually a prefab.

Comment
Add comment · Show 2 · 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 tpainton · Nov 02, 2015 at 02:34 PM 0
Share

Thanks for the update. You are a very helpful person. (Despite me being a bonehead in previous thread). This is perplexing because Hack$$anonymous$$anager is instantiated. I have done some searching and it appears that deter$$anonymous$$ing at runtime if an object is a prefab vs. an instance isn't easy, and some say impossible.

When looking at HackApp, the gameObject which holds Hack$$anonymous$$anager, HackApp is actually "HackApp(Clone)" so it certainly appears to be an instance of a prefab.

avatar image Pharan tpainton · Nov 02, 2015 at 02:41 PM 0
Share

So to be super clear. Both the parent, and the child are instantiated?

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

34 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 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

How to make script affect only one this game object 2 Answers

error Int to string?Assets/Scripts/MyConnect.cs(61,60): error CS0029: Cannot implicitly convert type `int' to `string' 1 Answer

How can i limit object dragging area in my inventory? 0 Answers

Door open script opens all the doors in the scene 3 Answers

Make an object a certain distance from me. 2 Answers


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