UGUI comprehensive understanding, UGUI comprehensive
With unity3d 4.6 ~ 5. x + the new UI system finally met you. This article will not introduce how to use UI controls such as buttons and scroll bars. For details, refer to Unity Manual. This article focuses on how to understand the UI system design, in order to better use it in practice.
RectTransform
The Unity UI system uses RectTransform to implement basic layout and hierarchical control. RectTransform inherits from Transform, so all features of Transform are also RectTransform. Based on the Transform, RectTransform adds the axis, anchorMin, anchorMax, and sizeDelta ).
Axis: indicates the center of the UI element and the point position expressed in percentage relative to the range of its rectangle, which affects positioning, scaling, and rotation.
Anchor: relative to the Child rectangle area of the parent rectangle, each boundary value of this rectangle is expressed as a percentage.
Size Variation: The Size Variation of the Child rectangle defined by the anchor. the area after merging with the child rectangle defined by the anchor is the final UI rectangle.
On the Inspector interface, to more easily adjust the RectTransform attributes, the position and width and height (adjust the position and sizeDelta directly) are displayed when the two points of the anchor are duplicated ), otherwise, the offset of the rectangle boundary relative to the anchor is displayed (after calculation, it is assigned to the position and sizeDelta ). In the program, RectTransform adds the anchoredPosition and rect attributes to facilitate programming.
The RectTransform component is also responsible for organizing the hierarchical relationship of GameObject. In the UI system, the Child UI objects are Always overwritten and displayed on the parent UI objects. The lower UI objects are Always overwritten and displayed on the top UI objects. This design avoids tedious deep settings. In the program, Transform adds SetSiblingIndex, GetSiblingIndex, SetAsFirstSibling, and SetAsLastSibling methods to conveniently modify the object's hierarchical sequence.
EventSystem
If you use the UI system, the EventSystem object is automatically created. This object monitors user input. By default, you can use the keyboard and mouse to input data on your computer and touch the data on your mobile device. However, if you want to develop devices such as surface, you can enable both types of input at the same time. When you need to block user input, close this object. UnityEngine. EventSystems. EventSystem. current saves the EventSystem object of the current activity.
Canvas
Canvas is the root of all other UI objects. In a scenario, there is no limit on the number and level of Canvas. The child Canvas uses the same rendering mode as the parent Canvas. A Canvas has three rendering modes:
Screen Space-Overlay: the UI elements are displayed on any camera Screen in 2D mode relative to the Screen Space. This is a very standard UI style. Typical Example: a large number of window, text, and button strategy games.
Screen Space-Camera: the UI elements are displayed by the specified Camera relative to the Screen Space. The parameters of the Camera affect the display results. You can think of Canvas as a sub-object of the camera. Typical Example: 3D HUD on the shooting game screen.
World Space: compared with the World Space, the UI elements have the same location and occlusion relationships as the objects in other scenarios. It is usually used for very innovative UI design. Example: in-game mobile phone screens and scenario-Bound game guides.
CanvasScaler
This component is responsible for screen adaptation. The UI system uses RectTransform to calculate the UI location and size, but this is not enough. How can I adapt the designed UI to different resolutions, aspect ratios, and DPI? This component provides the following three adaptation methods. Note that none of the adaptation methods will change the aspect ratio and relative positioning of the UI.
Constant Pixel Size: Adjust the Pixel Size of the Canvas to keep the zoom unchanged. It means to adjust the pixel size of the Canvas to be consistent with that of the screen without changing the Scale Factor of the Canvas on any screen. You can adjust the zoom factor of the Canvas manually or by code. This is the default UI system adaptation solution. For example, if the two resolutions have the same UI display differences, although the UI element positioning and size of different screens have not changed (the two white elements in the figure are located in the upper left corner and lower right corner of the screen respectively ), however, the UI elements on a small screen occupy most of the screen space and appear more crowded. This is the disadvantage of this method of adaptation. The small screen is too crowded and the large screen is too empty. The screen resolution and DPI are not taken into account. However, the advantage of this mode is that the UI element can maintain the details of the design (because there is no scaling ). This mode may apply: You want the UI to be displayed in the original size within a certain range, in this way, the UI display can be as clear as possible, and gamers with larger screens can have a broader view, but on a screen that is too small or too large, you can adjust the scaling factor through a program, so that the UI of a small screen is not full or the UI cannot be found on the large screen.
Scale With Screen Size: scales according to the Screen resolution. This may be the most convenient adaptation method for most games. In this mode, you need to specify a design resolution and then specify the scaling algorithm. Regardless of the scaling algorithm, if the actual aspect ratio is the same as the designed aspect ratio, the UI will be scaled proportionally. In fact, Canvas only keeps its size consistent with the design resolution. If the actual aspect ratio is different from the designed aspect ratio, then the scaling algorithm will affect the display result. There are three Scaling algorithms: expansion, contraction, and matching width and height. The logic of the extension algorithm is to expand the shorter side of the Canvas (in Aspect Ratio) so that the Canvas aspect ratio is consistent with that of the screen. As shown in the left figure below, the design resolution aspect ratio is (red box). The actual screen is wider, so the width of the Canvas is increased to match the screen. Such an algorithm will always make the UI more open on different screens with different aspect ratios ". The logic of the contraction algorithm is to contract the longer side of the Canvas (on the aspect ratio) so that the Canvas aspect ratio is consistent with that of the screen. As shown in the following figure, the design resolution aspect ratio is (red box), and the actual screen is narrower, so the Canvas height is reduced to match the screen. Such an algorithm will always make the UI more "Compact" on screens with different aspect ratios ". The algorithm logic for matching the width and height is to adjust the width and height of the Canvas Based on the specified weight to make the Canvas Aspect Ratio consistent with that of the screen. As shown in the figure below, the design resolution is a red box with the same weight (0.5) as the width and height. The width and height of the Canvas on the actual screen are adjusted to match the screen. This algorithm aims to keep the original UI design as much as possible through adjustable width and height weights.
Constant Physical Size: Adjust the Physical Size of the Canvas to keep the scaling unchanged. It means that the DPI of the Canvas is not changed on any screen, but the physical size of the Canvas is always the same as that of the screen. This statement may be more difficult to understand than Constant Pixel Size. In fact, they are essentially the same, but Constant Pixel Size maintains scaling through logical Pixel Size adjustment, the Constant Physical Size is adjusted physically to maintain scaling. In this mode, you must specify a factor for converting the physical size of a pixel (enter 96 to facilitate development on windows ). When running, the Canvas pixel size and zoom factor are calculated based on the dpi reported by the specific device. From the design intent, this pattern aims to use physical units rather than pixel units during development. This will only make the work of programs and art complex, and the actual use value is not high. Because developers are more concerned about the designed pixel resolution, they need to draw clear pixel-size images! If developers and gamers use ultra-high DPI monitors in the future, they may focus more on physical sizes.
Selectable
The base class that can interact with the UI component. It is responsible for responding to user input, generating visual changes, switching navigation targets, and handling General UI events.
Transition: interactive components have four visual states: normal, highlighted, pressed, and disabled ). Selectable performs status Switching Based on the user input and the current status. There are four types of visual effects: none, color tint, sprite swap, and animation. You must add an animation or component to use the animation effect. The animation controller contains the preceding four states. You can use the Auto Generate Animation button to automatically add components and create an Animation controller.
Navigation: You can use the keyboard and game controller to switch the Navigation target. If you want to develop a game (host game) that can be played only with the game controller, this function is very important, because gamers cannot use touch screens without a mouse, they can only use buttons to switch their navigation targets. This function has been designed to be perfect, so that you can handle almost nothing. Five navigation options are available: None, Horizontal, Vertical, Automatic, and Explicit ). If not explicitly specified, the navigation system automatically finds out whether there are the most suitable Switching targets in four directions based on the rectangle position and size of each UI element. If you select to explicitly specify, You need to specify the switching target (Selectable) for the four directions ). Click the Visualize button on the Inspector interface to view the navigation path (yellow lines in the navigation bar). You can set the default selected objects in EventSystems.
Common events: OnSelect, OnDeselect, OnPointEnter, OnPointExit, OnPointDown, OnPointUp ,.... Override these methods to define your own interactive components. An example is provided to illustrate how to implement custom controls.
Auto Layout
Automatic Layout is used to simplify the layout of the UI. The automatic Layout is based on the RectTransform Layout system. It contains two concepts: Layout Elements and Layout Controllers.
The layout element contains parameters such as minimum size, preferred size, and optional size. The layout controller adjusts the size and position of the layout element based on these parameters. The basic principle of layout controller adjustment is: first assign the minimum size, then assign the preferred size if there is enough space, and finally allocate the optional size if there is space. A game object containing the RectTransform component is a layout element. Adding some components will modify the parameters of the layout element. LayoutElement is a component used to modify default layout parameters. The layout controller exists in the form of multiple components, which control the size and position of the layout element of itself or sub-level. For more information about the functions and usage of various layout controller components, see the Unity documentation.
Rich Text
By default, the Text component displays all texts in a single style. Rich Text can enrich the display style, such as highlighting some texts. In fact, rich text functions can be used not only in the UI system, but also in the Legacy GUI system and Debug.
Rich Text uses html tags. For example, "<B> Hello </B>" is displayed as a bold "Hello ". These labels can also be nested. Available labels include B (BOLD), I (tilt), size (size), and color (color ). The value of size and color must be specified, for example, "<size = 50> Hello </size>" "<color = # FF0080FF> Hello </color> ". The unit of the size attribute is pixel. The color attribute uses the hexadecimal format of RGBA to represent the color or directly fill in the common color name. For example.
If TextMesh is used, you can also use the material and quad labels. Material must specify the material subscript in the material array, for example, "<material = 1> Cool </material>"; the quad tag has no end tag, which is usually used to display an image in the text, for example, "This is me: <quad material = 2 size = 24 x = 0 y = 0 width = 1 height = 1/> ".
UnityEvent
A serializable event type that can be displayed on the Inspector. The typical purpose is the OnClick event of the Button. Drag an object or component to the box to select the method called when the event is triggered. The optional method must be public, return-free, and contain 0 or 1 serializable parameter. You can also call the set type attribute. You can also use UnityEvent in your own script. As long as you define a serialized field, it will look the same as OnClick!
UnityEvent can be added, removed, or called through code, which is a packaging of C # delegate. In addition, there is a generic version of UnityEvent, which supports a maximum of four parameters. However, because it is a generic abstract class, it must be inherited before use.
[Serializable] public class MyEvent : UnityEvent<GameObject> { } public MyEvent myEvent;
UnityEvent is called by using the Invoke method in the program. The parameter types and quantities required by Invoke are consistent with those of generic parameters. However, the Inspector can only be filled with 0 or 1 parameters. The method added to the Inspector cannot directly obtain the parameters passed during Invoke.
Custom Controls
The example of this custom control shows how to flexibly use various functions of the UI system to meet various wonderful demands.
Requirement: implement a control for role point allocation. A role has a certain number of points and can be assigned to multiple attributes. Each attribute can be assigned a certain range of points, the sum of attribute points cannot exceed the number of points owned by the role. The general implementation method is to display the remaining points and multiple attribute slide for each role. dragging each slide will change the remaining points. Here we need to put all the slide into a large slide, and you can drag each slide directly. The advantage is that you can intuitively see the comparison of the total capabilities of each role and the remaining allocable points. The following figure shows the design drawing.
First, we need to analyze this requirement: the entire slide represents the total number of points; all slide are left aligned and spliced; each slide has its own maximum and minimum values; the total length of all slide cannot exceed the entire slide; each slider is interactive. The preliminary assumption is that each slider has a component that inherits Selectable and overwrites the press and pop-up events. In this process, the length of the slider is controlled. But how can I keep all the slider always left aligned? A direct idea is to use horizontal automatic layout. But here we do not do this (you can try to implement this), but make full use of the RectTransform anchor function to let each slider to the right of the previous slider. In this way, each slider must be a child of the previous slider. The solution is ready. Let's take a look at how to make it simpler and more common. Fill in all initial parameters in a root component. This component will automatically create all the slide based on these parameters. The following figure shows the parameters required for a slider:
// Attribute [Serializable] class Attribute {public string name; public Sprite image; public Color color; public int min; public int max; public int value; [NonSerialized] public ValueSlider valueSlider ;}
Min, max, and value are the minimum, maximum, and initial points respectively. The last ValueSlider is our custom Selectable component. You can save the corresponding component reference in the attribute to facilitate modification. ValueSlider is defined as follows:
// Slider class ValueSlider: Selectable {MultiAttributesSlider _ lower; Attribute _ attribute; public void Init (extends multiAttributesSlider, Attribute attribute) {_ MultiAttributesSlider = multiAttributesSlider; _ attribute = attribute ;} public override void OnPointerDown (PointerEventData eventData) {base. onPointerDown (eventData); _ multiAttributesSlider. beginSlide (_ attribute, eventData);} public override void OnPointerUp (PointerEventData eventData) {base. onPointerUp (eventData); _ multiAttributesSlider. endSlide ();}}
During initialization, save the root component (named "multi-attribute slide") and the corresponding attribute reference, and then call the start slide and end slide methods of the root component respectively when you press and press. There is no actual content, and the main operations are on the Root component. The root component is defined as follows:
Class MultiAttributesSlider: MonoBehaviour {// total number of points [SerializeField] int _ totalValue; // Attribute array [SerializeField] Attribute [] _ attributes; // number of remaining points int _ restValue; // float pixelsPerPoint of the number of points; // Save the information Attribute _ currentAttribute = null when the slider is pressed; PointerEventData _ eventData; int _ beginValue; int _ beginRestValue; // call public void BeginSlide (Attribute currentAttribute, PointerEventData ev EntData) {_ currentAttribute = currentAttribute; _ eventData = eventData; _ beginValue = currentAttribute. value; _ beginRestValue = _ restValue;} // call public void EndSlide () {_ currentAttribute = null when the mouse is released from any slider;} // initialize void Awake () {// you need to use a custom editor to ensure that the parameters entered by Inspector are completely reasonable. This step is ignored in this example. // Count the number of used points int valueCount = 0; for (int I = 0; I <_ attributes. length; I ++) {valueCount + = _ attributes [I]. value;} // calculate the number of remaining points _ restValue = _ totalValue-valueCount; RectTransform lastParent = transform as RectTransform; // calculate the pixel size of a point. pixelsPerPoint = lastParent. sizeDelta. x/_ totalValue; // create each slider. A better way is to use a button in the Custom editor to generate all the slide for (int I = 0; I <_ attributes. length; I ++) {GameObject slider = new GameObj Ect (_ attributes [I]. name); // initialize RectTransform rect = slider. addComponent <RectTransform> (); rect. setParent (lastParent, false); rect. localScale = Vector3.one; rect. localRotation = Quaternion. identity; rect. response = new Vector2 (0, 0.5f); rect. anchoredPosition = Vector2.zero; if (I = 0) {rect. anchorMin = Vector2.zero; rect. anchorMax = new Vector2 (0, 1);} else {rect. anchorMin = new Ve Ctor2 (1, 0); rect. anchorMax = Vector2.one;} rect. sizeDelta = new Vector2 (pixelsPerPoint * _ attributes [I]. value, 0); // initialize Image image = slider. addComponent <Image> (); image. sprite = _ attributes [I]. image; image. color = _ attributes [I]. color; image. type = Image. type. sliced; image. fillCenter = true; // initialize ValueSlider _ attributes [I]. valueSlider = slider. addComponent <ValueSlider> (); _ attributes [I]. valueSlider. init (this, _ attributes [I]); // use the current RectTransform as the parent lastParent = rect ;}}// Update the slider value void Update () {if (_ currentAttribute! = Null) {// calculates the point variation corresponding to the sliding distance. int deltaValue = Mathf. roundToInt (_ eventData. position. x-_ eventData. pressPosition. x)/pixelsPerPoint); // the change in the number of points restricted by the minimum and maximum values deltaValue = Mathf. clamp (_ beginValue + deltaValue, _ currentAttribute. min, _ currentAttribute. max)-_ beginValue; // update the remaining number of points _ restValue = _ beginRestValue-deltaValue; // if the remaining number is used up, reduce the number of points if (_ restValue <0) {deltaValue + = _ restValue; _ restValue = 0;} // update current point _ currentAttribute. value = _ beginValue + deltaValue; // updates the slider size (_ currentAttribute. valueSlider. transform as RectTransform ). sizeDelta = new Vector2 (pixelsPerPoint * _ currentAttribute. value, 0 );}}}
The meaning of the Code is clearly written in the above analysis and comments. This component is better suited to a custom editor, but you don't want to write it here. If you are interested, try it.
The following is the test. Create a slide background, add this script, fill in the parameters, and finally look like this:
Then run it. The figure will not be cut off. It is the above design chart... and a photo will be taken at the end.
The CanvasGroup component can be added to control the interactivity and opacity of the entire sub-level. It is very convenient to create a non-Interactive UI object or to control the opacity of a window as a whole.
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.