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 Kilmor · Mar 04, 2015 at 01:45 PM · uilayoutrecttransform

How do I layout dynamically instantiated UGUI components?

TLDR: I am dynamically instantiating item renderers from a prefab for a UGUI List component I am making. I don't know how to layout the List in script because the item renderer's RectTransform.rect does not specify a width or height until the next frame. How do I layout dynamically instantiated UGUI components properly?

Background: I am currently building a UI component library (think List, ComboBox, etc.) using UGUI. The goal is to create completely dynamic and reusable components that can be dropped into any UI layout. I have had some very good success so far, but I have come a question in the process: how do you dynamically layout components (properly) using the UGUI framework?

UGUI Background Resources Unity Documentation: http://docs.unity3d.com/Manual/UISystem.html

UGUI Source: https://bitbucket.org/Unity-Technologies/ui/src/

I am currently working on a dynamic list component. Hopefully these are some requirements that will help explain what I am working on and some of the challgenges I am having:

  • The List shall be a prefab.

  • The List shall allow a designer to drag-and-drop the list prefab into any UI without needing custom adjustments.

  • The List shall allow a designer to assign any "item renderer" component that will be rendered for each visible data object within the list.

  • The List shall be driven by a "data provider" that supports any data type.

  • The List shall automatically create, destroy, and otherwise manage a series of "item renderers" that are use to display the data in the "data provider."

  • The List shall render default "item renderers" of the assigned type while in Edit mode for a designer to preview how it looks.

  • The List shall allow a designer to specify the maximum number of visible rows (if vertical) or columns (if horizontal) that can be displayed at one time.

  • The List shall allow a designer to toggle between "vertical" and "horizontal" layouts.

I have been able to successfully implement almost all of those requirements, however I have not been successful in laying out the item renderers in a single Update. The root of the problem is in dynamically instantiating the item renderers. For simplicity, lets say one item renderer gets instantiated for each item in the data provider. When each item renderer is instantiated its RectTransform has no width or height. This means I cannot properly layout the component since I am working with unknown dimensions. Is it possible to measure the item renderer in the same frame that it is instantiated?

I currently have an invalidate cycle in the Update function. When any of the lists properties are modified the component trips a flag "invalidateProperties." Then in the Update loop I check to see if the flag is true, and if so I perform a layout based on what changed. This includes creating new item renderers, destroying extra item renderers, updating item renderers with data so they can initialize their own displays, and performing an automatic layout in the case of toggling the horizontal or vertical property on the list. During this invalidate cycle I cannot get the RectTransform.rect to calculate its size in the current frame on newly instantiated item renderers. This seems to be because Unity's layout process takes place after the current frame. Yes, I have also tried checking in LateUpdate, the RectTransform.rect still is not initialized there either.

In parsing through some of the UGUI source I have found an interesting call: CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild()

Unity Documentation: http://docs.unity3d.com/ScriptReference/UI.CanvasUpdateRegistry.html

It appears this allows you to recieve callbacks for Prelayout, Layout, and PostLayout. This is a good start because I should probably be moving my item renderer layout to one of these events. The problem is that the item renderers dimensions are still not initialized until PostLayout. Even doing this, performing a layout does not work properly. It appears that the layout is being correctly updated, however it is not "refreshed" in PostLayout; things do not move to the correct positions even though they have the correct positions and sizes assigned to them. I believe this is because PostLayout is true to its name, it is a callback that takes place AFTER the layout process. Putting code here seems hacky to me and doesn't even solve my problem, maybe I am using it wrong?

I have not seen any UGUI components that use dynamically instantiated components such as item renderers, so I don't know if this is something that UGUI currently supports or not. I just came from an AS3 position (with C++ before that) and I would love to see some in-depth documentation like the following:

Example AS3 Layout Documentation: http://help.adobe.com/en_US/flex/using/WS460ee381960520ad-2811830c121e9107ecb-7fff.html

There are two giant sections breaking down the exact lifecycle, what should be done in which functions, and also a breakdown on the steps needed to write your own custom component with additional links to even more supporting documentation.

I do know that UGUI is still very new, and am I very greatful that Unity is taking the time to put a foundation for a UI framework in. UGUI is a great start, and I hope to see its continual evolution as time comes! Thank you for your insight and any comments you may have.

Unfortunately I cannot post any code here, as it is proprietary to my company. I will be happy to provide as much additional information as needed, though! Upon completion, I would like to make the library accessible through the Unity Asset Store to help those that have complex UI woes.

Comment
Add comment · Show 2
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 meat5000 ♦ · Mar 04, 2015 at 03:37 AM 0
Share

You can delay its execution until the next frame so it receives the correct information

avatar image Kilmor · Mar 04, 2015 at 03:14 PM 0
Share

Update: I have been able to successfully delay the execution until the next frame. It does work at runtime, however in the editor it does not.

The editor only updates when the inspector changes. I implemented a workaround by implementing my own custom inspector that triggers an update call. That does work, however it only works when you have the UGUI GameObject in the hierarchy selected. This means when I am ending a play session and am returning to edit mode, the layouts do not size correctly and everything gets reset to the default sizes.

I haven't been able to find a way to get UGUI to update component sizes AND be able to do a layout in a single frame. The search continues... :)

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by RazaTech · Feb 14, 2018 at 10:54 AM

Hello ! This might give you confidence :P. you are right we have to wait for next frame for updated size.

what I did is. CommitData function as coroutine . when your data is set for example,

inputLabel.text = label; wait for one frame

Then do calculations and set position and size.

right now unfortunately there is no life cycle to implement.

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

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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

How to Save Property Values of a Component on a Scriptable Object? 1 Answer

Horizontal Layout Group making a Scroll Rect's Content rect width to be negative 1 Answer

Stretching 90° rotated RectTransform to the size of the Canvas 0 Answers

Resizing UI Image but with minimum width 2 Answers

RectTransform.Rotate with custom speed 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