您现在的位置是:首页 >技术教程 >unity进阶学习笔记:UI框架网站首页技术教程

unity进阶学习笔记:UI框架

Raine_Yang 2024-06-17 10:13:44
简介unity进阶学习笔记:UI框架

一般来说,一个游戏内具有大量的UI组件。如果只是使用之前的消息框架处理所有UI相关的信息会十分复杂且低效。因此我们将UI系统作为一个独立的系统进行处理,并搭建一套UI框架

UI框架主要分3层:UIManager用于管理所有UI组件,UIController用于管理某一个UI面板,如角色信息面板,商店面板等。UIControl用于控制每一个单独的UI组件

在UI系统中,我们放弃之前消息系统中使用的广播框架,因为该方案需要专门为每一个UI组件编写发送和接受消息的方法,过于复杂。我们希望通过UIController和UI Manager可以让每一个UI组件访问到任何一个另外的UI组件。如在“商店”控制器中的按钮组件可以直接更改“背包”控制器中背包格子图片,直接实现商店购买物品加入背包的功能。

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;
    }


}

这里我们创建一个字典用于保存UIManager下面所有UIController。

在SetActive方法中控制各个UIController的开关。GetUIControl用于查找一个特点的UIControl。注意这里我们先找到对应UIController,再在UIController下面找到UIControl。这一方法可以减少要遍历的组件个数,提高效率,同时避免不同UIController下面出现同名组件的问题

UIManager uiManager = UIManager.Instance as UIManager;

注意这一句的作用。UIManager类继承ManagerBase,而ManagerBase继承SingletonBase并将其类型设为ManagerBase。这导致UIManager.Instance类型依然属于ManagerBase,出现问题。因此这里我们需要强制将ManagerBase向下转换为UIManager

2 UIController

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>();
            }
        }
    }
}


在UIController中创建字典用于保存该UIController下面的UIControl。

在Awake方法中,我们先在UIManager的字典里注册该组件。同时,考虑到在一个UIController下可能会有很多UI组件,手动添加会过于麻烦。于是我们遍历UIController下面的UI物体并为每一个添加UIControl组件

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);
        }
    }
}

在Awake方法里,我们将该UIControl组件注册到UIController中。这里我们已经完成了框架的搭建。后面的ChangeText,ChangeImage,AddButtonClickEvent,AddInputFieldEvent都是方便UI操作的函数。这里拿AddButtonClickEvent为例:

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

AddButtonClickEvent参数类型为UnityAction,该类型可以理解为一个匿名方法,使用UnityAction类型需要导入UnityEngine.Events。在下面程序中我们获取到该游戏物体的按钮组件control,并在control上挂载对action的监听。

对于其他方法实现原理类似,在后续开发中还可以根据实际需求加入更多的UI控制方法。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。