Special FlexContainer that sits at the top-level of all FlexBuilder layouts and contains semi-global settings that control how the Flexbox layout integrates with the local UnityUI/RectTransform layout. You cannot use Flexbox without having at least one RootFlexContainer on your Canvas.
Each flexbox layout has a single RootFlexContainer: layout is applied specificaly to 'all descendent FlexContainers and FlexItems of the RootFlexContainer'.
You can have multiply RootFlexContainers on a single Canvas - each one will perform its layout separately and independently, and will ignore the others.
Creating from script
Recommended to use CreateFlexComponents which simplifies the creation/adding of new instances
SizeMode: standalone? or scrollview?
Most RFCs use a sizeMode of 'UNITY_UI': this means the RFC itself is sized by the RectTransform, 100% controlled by Unity. The RFC then sizes and positions all its children and descendents ignoring RectTransform but using Flexbox instead.
However: scrollviews / scrollrects need to dynamically auto-resize themselves based on their (changing) contents. For those situations, the RFC needs to be placed in a sizeMode of 'FIT_CONTENT', which resizes the RFC after every relayout to make it precisely fit its content.
FIT_CONTENT is also sometimes useful in advanced / complex layouts, but is only fully supported for scrollviews.
Each RFC can have a unique LayoutAlgorithm instance (NOTE: prior to v4.0, all RFC's had to share the same LayoutAlgorithm). The LayoutAlgorithm provides 99% of the implementation of Flexbox, and you can drag/drop different algorithm implementations onto your RFC in the Inspector to change which one it uses.
For most projects you'll always want to use the 'most recently released' LayoutAlgorithm - and the RFC's inspector will automatically prompt you if it detects you're using an out-dated LayoutAlgorithm.
However: new LayoutAlgorithms sometimes fix bugs in old ones that you might be relying on for your game UI (ie. you already accounted for the bug when creating your UI) - in that case, upgrading would force you to go back and re-do potentially many parts of your UI. In those cases you may wish to keep your RFC using the original LayoutAlgorithm, while using the new LayoutAlgorithm for new RFCs you create going forwards.
Differences between RootFlexContainer and FlexContainer
- FlexContainers cannot perform layout unless one of their ancestors is a RootFlexContainer
- ... RootFlexContainers always perform layout for themselves and all their descendents.
- FlexContainers should always have an attached FlexItem (to allow them to be embedded in a FlexContainer/RootFlexContainer)
- ... RootFlexContainers MUST NOT have an attached FlexItem (since they cannot be embedded in anything)
- RootFlexContainers hold 'shared' settings for all the FlexContainers/FlexItems in the layout
- RootFlexContainers control which LayoutAlgorithm is used for all their descendents
Embedding RootFlexContainers inside RootFlexContainers
When performing layout on a RootFlexContainer, it will process all child FlexItems, and for each one that has a FlexContainer attached: also all (grand)child FlexItems of the (child)FlexContainer. This is then processed recursively on all descendent GameObjects.
This continues down the tree until a FlexItem is found that has no FlexItem children OR has a RootFlexContainer attached. (NOTE: v4.x does not currently allow the RootFlexContainer to be attached directly to a FlexItem; you need instead to insert a 'dummy' gameobject between the two, and use RectTransform settings to make the dummy object expand to fill the parent FlexItem. You can then place the RootFlexContainer as the sole child of this dummy object).
This allows you to embed a second RootFlexContainer (RFC) inside a first. This is rarely used in normal situations, but is common when putting scrollviews / scrollable content inside a flexbox layout: Unity requires us to separate the 'scrollable' content into a separate sublayout, and the secondary RFC provides that.
public class RootFlexContainer : FlexContainer, IFlexComponent, IUpgradeableComponent, ILayoutGroup, ILayoutElement
- (Boolean) containerInspectorsShowDebugOptions
When enabled the Inspectors for all FlexContainers in this RFC will show additional UI options related to debugging
- (Boolean) debugInvalidations
- (Boolean) debugVerbose_ContentSizes
When this is true, AND an individual FlexContainer has showDebugMessages turned on ... additional verbose output is included on the precise sizing of ContentSizes of FlexItems and the attached UnityUI elements (Button, Text, Inputfield, etc).
This can add a large amount of extraneous logging, so is generally switched off unless you have ContentSize problems
- (Boolean) fitContentAlignsToTopWhenContentSmallerThanViewport
- (IGizmoRenderer<FlexContainer>) gizmoRendererForFlexContainers
Controls all rendering of Gizmos for the FlexContainers within this RootFlexContainer
- (IGizmoRenderer<FlexItem>) gizmoRendererForFlexItems
Controls all rendering of Gizmos for the FlexItems within this RootFlexContainer
- (Boolean) suppressCommonUIToolkitBugWarnings
When this is true, error messages due to bugs in Unity's UIToolkit are hidden.
As of September 2022 Unity still hasn't fixed some obvious, glaring, bugs in UIToolkit. We're still waiting...
- (IFlexboxLayoutAlgorithm) layoutAlgorithm
The LayoutAlgorithm that will be run for all layout operations on this RootFlexContainer (RFC) and all its descendents. This is required for the RFC/FlexBuilder to work at all.
When creating a new RFC in the UnityEditor (using the inspectors etc) FlexBuilder will automatically lookup the global settings for FlexBuilder, and assign the 'default' LayoutAlgorithm to the new RFC. Most of FlexBuilder's API calls will also do this - but this only works in the Editor (due to design flaws in Unity itself) - for your own code that runs at Runtime/Player you will usually need to explicitly assign a LayoutAlgorithm instance immediately after creating a new RFC.
We do not allow 'null' to be provided as a value.
Similarly: our override of Reset() prevents nulling of this variable
- (Nullable<RectTransform.Axis>) scrollsInAxis
RFCs installed in a ScrollRect can extend infinitely (And scroll) in either horizontal or vertical, currently scrolling BOTH at once is unsupported (it is possible in Flexbox, but it's undefined: while CSS allows full expansion, Flexbox doesn't define what that would mean or how it would work - there is a very complicated and unspecified feature in the spec called "Orthogonal Flow" for dealing with this, but the CSS3 authors still haven't solved the problems it causes, so there's not (yet) an official meaning to it.
In the meantime, I've created this property so that code which is dependent upon scroll-direction can record its dependence, and it will be easy to discover and modify later in a few years if CSS3 solves this problem for Flexbox.
- (RootContainerSizeMode) sizeMode
See the 'SizeMode' section in main class description.
- (ITreeUpdateAlgorithm) treeUpdater
Sub-algorithm that controls 'when do we need to run a relayout, and how many items (children, grandchildren, ancestors, parents, etc) need to be relayouted ... which ones can remain unchanged?'.
As of v4.3+, this is required for the RFC/FlexBuilder to work at all.
See layoutAlgorithm for instructions on what you have to do from scripts if you create an RFC programmatically - you ALSO need to create/assign an instance of this object.
Similarly: our override of Reset() prevents nulling of this variable
- (void) OnEnable_ConsiderRelayouting()
To workaround Unity's core MonoBehaviour bugs, we 'guess' if this RFC is being instantiated by checking whether it's already got a non-null transform.parent
- (void) OnTransformParentChanged()
- (void) Reset()
Constructor only exists to set defaults that are unique to this subclass - it has to behave more like a BrowserWindow and less like a display:flex element (by design - CSS browsers define the root of the DOM tree with different defaults than Flexbox's defaults, for backwards compatibility with original / early HTML)
- (void) ScriptForceRelayoutFullTree(String, Boolean)
This should only be used rarely.
TL;DR: Good reasons to use this:
- a layout got corrupted by a bug and now you need to force-refresh everything in it
- you've upgraded to a new algorithm, and want to force-refresh everything, but for some reason the auto-relayouting logic didn't detect that you'd changed algorithm.
Any situation where you need to use this probably represents a bug or missing feature - please contact support and let us know!