Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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
1
Question by Skepper · Jul 11, 2018 at 01:27 AM · gameobjectbest practice

Best practice for finding game objects,Best practice for finding gameobjects

Hi Team,

I have a UI I'm setting up that I want to programmatically change content. See attached picture illustrating the hierarchy of objects.

alt text

I have a script on the BackgroundPanel which searches for individual items, for example, the textbox "heading", the textbox "LeftTextBox", and the object "ObjectRight" which may have a video player, a render image, or some other content (currently to be defined, which will be created later).

I currently have the following code to find each item by name - which obviously is totally static. It works, but what I'd like to know is - is there a "best practice" or better way to do this?

 public class UIContentController : MonoBehaviour 
 {
     Text leftText;
     Text linkBox;
 
     GameObject objectRight;
     GameObject heading;
 
 
     // Use this for initialization
     void Start () {
         heading = transform.Find("Heading").gameObject;
         leftText = transform.Find("LeftTextBox").GetComponent<Text>();
         linkBox = transform.Find("GeniusLink").GetComponent<Text>();
 
         objectRight = transform.Find("ObjectRight").gameObject;
     }
 }

If I use the code

 leftText = GetComponentInChildren<Text>();

Then I find the first text component, without finding the correct text component.

Thanks in advance for any assistance.

,Hi Team,

I have a UI I'm setting up that I want to programmatically change content. See attached picture illustrating the hierarchy of objects.

alt text

I have a script on the BackgroundPanel which searches for individual items, for example, the textbox "heading", the textbox "LeftTextBox", and the object "ObjectRight" which may have a video player, a render image, or some other content (currently to be defined, which will be created later).

I currently have the following code to find each item by name - which obviously is totally static. It works, but what I'd like to know is - is there a "best practice" or better way to do this?

 public class UIContentController : MonoBehaviour 
 {
     Text leftText;
     Text linkBox;
 
     GameObject objectRight;
     GameObject heading;
 
 
     // Use this for initialization
     void Start () {
         heading = transform.Find("Heading").gameObject;
         leftText = transform.Find("LeftTextBox").GetComponent<Text>();
         linkBox = transform.Find("GeniusLink").GetComponent<Text>();
 
         objectRight = transform.Find("ObjectRight").gameObject;
     }
 }

If I use the code

 leftText = GetComponentInChildren<Text>();

Then I find the first text component, without finding the correct text component.

Thanks in advance for any assistance.

unityobjectlist.jpeg (32.2 kB)
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
1
Best Answer

Answer by JVene · Jul 11, 2018 at 05:01 AM

You've basically figured out what "Find" does, and that it's not particularly thrilling.

You've also identified what I find all but useless about GetComponentInChildren.

Find also doesn't descend into children, so you have to manually iterate through a hierarchy when that becomes an issue.

However, not all is lost if you're looking for something better, which does depend on your use case.

To preface, the assumption I'm making with the suggestion that follows is that UIContentController is a singleton (there's only 1, and it could be considered a "global" entity, either available to all, or supervisory such that lots of objects look up to it for centralized control).

I'd have the kids call home.

Instead of this parental, supervisory object searching the children for the components, I would consider having the kids do that. For this to work any better, you'd need some quick, simpler means for the kids to find this parent script (UIContentController). It is not practical to assume the order in which start is called among objects, but it seems to me (and this might be documented, but I've not read it) that object starts are called from the lowest children upwards. It is likely UIConentController's start function won't be called before the children's start script executes (so you can't rely upon UIContentController's start script to initialize the static UICC for them). The script, UIContentController, will exist, however, and can be found.

So, I'd use "lazy initialization" of a global reference to UIContentController. As odd as this may seem, put a:

  static private UIContentController UICC = null;

In your class. This is, basically, a globally accessible value, but it starts out null (you don't have an instance to one at this point - the very early initialization of the code, and remember I said the assumption is that there will only be 1).

It is private in this example so that only UIContentController can assign it (that keeps it under control).

Next, I'd suggest a static public member function like:

 static public UIContentController GetUICC() {...}

The purpose of this function is simply to return UICC, but before doing that check to see if it is ==null. If it is, this is a call from the first child trying to register. In the chilren's start function, they can:

 UIContentController uicc = UIContentController.GetUICC();

Then use the uicc to register themselves (more in a moment).

For the first call made by a child to GetUICC, the static UICC will be null. The function will have to search the hierarchy for the object that owns the UIContentController script component, get the component and set UICC to that (so that all subsequent children will find it much faster).

Since I have no idea where your UIContentController is located, I can't write a precise example, but it likely starts at the root, checks it's children (and if you know for certain the owner is at the top level, that might be all that needs to happen). If it is owned by a subobject (child of a top level object), you might already know where that is, so you might be able to tune a "find" command to go right to it.

This approach means a "find" will only have to happen once. Subsequent calls from children will use the cached static UICC.

So, when the "heading" object start function executes, it can call the parent with something like:

 UIContentController.GetUICC().SetHeading( transform.gameObject );

The "ObjectRight" can do something similar.

LinkBox might:

 UIContentController.GetUICC().SetGeniusLink( GetCompoment<Text>() );

In this way, the kids call home when they start, the parent is only "found" once, and all is a bit faster.

Of course, I'm using member functions in UIContentController as an example method, but you can choose as you prefer (properties, direct manipulation of UIContentController members even though that's considered naive).

This approach has one significant advantage. If you move the children or rename them, you don't have to change anything. With the approach you're using, where UIContentController finds the kids, if, say, GeniusLink were later made the child of a child, you'd have to change UIContentController's start function to find it in the new location. With this approach, the kid calls home no matter where it goes.

Comment
Add comment · Show 5 · 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 Skepper · Jul 11, 2018 at 09:26 AM 1
Share

Hi JVene,

Thank you for your response, that is far more comprehensive and detailed than I was expecting (having read some other Q&A posts here!)

Reversing my perspective of "children registering themselves" rather than "parent finding children" is something I hadn't thought about, but can see why you've raised it!

I currently haven't set up the UICC script as a unique, single only script (I was intending on adding the script to all the prefab UI objects I've created, probably 10ish) but I can see that your way is going to work better (and be more modular) in the long run (when I add more UIs and anything else in the future)

Thank you so much!

avatar image JVene Skepper · Jul 11, 2018 at 05:22 PM 0
Share

You're welcome ;)

If you're are going to have about 10 of these, then to keep the idea intact, I'd suggest you consider UIContentController as a base class, an create 10 small classes that derive from it, each named to identify what makes each unique among the 10, where the "GetUICC" is perhaps an abstract function in the base, and the static member is held by the most derived (and therefore a unique name for each static 'UICCxxx', so they're separate.

avatar image Skepper JVene · Jul 12, 2018 at 02:35 AM 1
Share

I was playing around with different data structures last night and thought inheriting from a base class (the UIContentController) would be a better way - I'm glad I was on the right thought path there!

However as all the Unity classes inherit from the $$anonymous$$onoBehaviour class, am I right in assu$$anonymous$$g I'd have to create UIContentController as an interface? So I can inherit both $$anonymous$$onoBehaviour AND UIContentController?

So for example, I'd have the UIContentController as an interface, then on each of the top level UI game objects, I'd have a UICCExample script which inherits the interface, that the child game objects would register to?

EDIT: Never $$anonymous$$d! reading a bit more on inheritance, I can see how this will work (As I said, I'm a beginner here!) Thanks!

Show more comments

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

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

Design Best Practice Question 1 Answer

Best practice : Image.enable vs go.SetAactive() 1 Answer

using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers

Projectile not 'projecting' because i have to use "var xxx : GameObject = Instantiate" 2 Answers

Position and rotation of a game object acting wired 0 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