Unity advanced study notes: UI framework

Generally speaking, a game has a large number of UI components. If you just use the previous message framework to process all UI-related information, it will be very complicated and inefficient. Therefore, we treat the UI system as an independent system and build a UI framework

The UI framework is mainly divided into 3 layers: UIManager is used to manage all UI components, and UIController is used to manage a certain UI panel, such as role information panel, store panel, etc. UIControl is used to control each individual UI component

In the UI system, we abandon the broadcast framework used in the previous message system, because this solution needs to write methods for sending and receiving messages specifically for each UI component, which is too complicated. We hope that through UIController and UI Manager, each UI component can access any other UI component. For example, the button component in the "Store" controller can directly change the backpack grid picture in the "Backpack" controller, and directly realize the function of adding items purchased from the store to the backpack.

1 UIManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIManager : ManagerBase<UIManager> {
    
    

    public Dictionary<string, UIController> UIControllerDic = new Dictionary<string, UIController>();

    public void SetActive(string controllerName, bool active) {
    
    
        transform.Find(controllerName).gameObject.SetActive(active);
    }

    public UIControl GetUIControl(string controllerName, string controlName) {
    
    
        if (UIControllerDic.ContainsKey(controllerName)) {
    
    
            if (UIControllerDic[controllerName].UIControlDic.ContainsKey(controlName)) {
    
    
                return UIControllerDic[controllerName].UIControlDic[controlName];
            }
        }

        return null;
    }

    public override byte GetMessageType() {
    
    
        return MessageType.Type_UI;
    }


}

Here we create a dictionary to save all UIControllers under UIManager.

Control the switch of each UIController in the SetActive method. GetUIControl is used to find a characteristic UIControl. Note that here we first find the corresponding UIController, and then find the UIControl under the UIController. This method can reduce the number of components to be traversed, improve efficiency, and avoid the problem of components with the same name under different UIControllers

UIManager uiManager = UIManager.Instance as UIManager;

Pay attention to what this sentence does. The UIManager class inherits ManagerBase, and ManagerBase inherits SingletonBase and makes its type ManagerBase. This causes the UIManager.Instance type to still belong to ManagerBase, causing problems. So here we need to force downcast ManagerBase to UIManager

2 UI Controller

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIController : MonoBehaviour
{
    
    
    
    public Dictionary<string, UIControl> UIControlDic = new Dictionary<string, UIControl>();

    void Awake() {
    
    
        UIManager.Instance.UIControllerDic.Add(transform.name, this);
        foreach (Transform trans in transform) {
    
    
            if (trans.gameObject.GetComponent<UIControl>() == null) {
    
    
                trans.gameObject.AddComponent<UIControl>();
            }
        }
    }
}


Create a dictionary in UIController to save the UIControls under the UIController.

In the Awake method, we first register the component in the UIManager dictionary. At the same time, considering that there may be many UI components under one UIController, adding them manually would be too troublesome. So we traverse the UI objects under UIController and add UIControl components to each

3 UIControl

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class UIControl : MonoBehaviour
{
    
    
    void Awake() {
    
    
        if (transform.parent != null) {
    
    
            UIController controller = transform.GetComponentInParent<UIController>();
            if (controller != null) {
    
    
                controller.UIControlDic.Add(transform.name, this);
            }
        }
    }


    public void ChangeText(string str) {
    
    
        if (GetComponent<Text>() != null) {
    
    
            GetComponent<Text>().text = str;
        }
    }

    public void ChangeImage(Sprite sprite) {
    
    
        if (GetComponent<Image>() != null) {
    
    
            GetComponent<Image>().sprite = sprite;
        }
    }

    public void AddButtonClickEvent(UnityAction action) {
    
    
        Button control = GetComponent<Button>();
        if (control != null) {
    
    
            control.onClick.AddListener(action);
        }
    }

    public void AddSliderEvent(UnityAction<float> action) {
    
    
        Slider control = GetComponent<Slider>();
        if (control != null) {
    
    
            control.onValueChanged.AddListener(action);
        }
    }

    public void AddInputFieldEvent(UnityAction<string> action) {
    
    
        InputField control = GetComponent<InputField>();
        if (control != null) {
    
    
            control.onValueChanged.AddListener(action);
        }
    }
}

In the Awake method, we register the UIControl component to UIController. Here we have completed the construction of the framework. The subsequent ChangeText, ChangeImage, AddButtonClickEvent, and AddInputFieldEvent are functions that facilitate UI operations. Here take AddButtonClickEvent as an example:

    public void AddButtonClickEvent(UnityAction action) {
    
    
        Button control = GetComponent<Button>();
        if (control != null) {
    
    
            control.onClick.AddListener(action);
        }
    }

The parameter type of AddButtonClickEvent is UnityAction, which can be understood as an anonymous method. To use the UnityAction type, you need to import UnityEngine.Events. In the following program, we get the button component control of the game object, and mount the action listener on the control.

The implementation principles of other methods are similar, and more UI control methods can be added according to actual needs in subsequent development.

Guess you like

Origin blog.csdn.net/Raine_Yang/article/details/130617771