HOME
BLOG
Unity UI系统(1)
9月 10 2022

UI系统介绍

| Unity2D 和 UI 的区别

Unity2D: 主要基于 Sprite Renender 和2D物理系统

UI: 由Canvas 及 UI组件组成(显示不基于Sprite Renender)

| UI 系统组成

Canvas 画布: UI 的根节点

EventSystem: 事件系统,基于这个才可以让我们按钮可以点击

Image / Text 等各种组件: 具体的功能组件,显示一个图片、制作一个按钮等


Image 组件

主要负责 图片 的展示

| 主要属性

  • SourceImage:源图片,在脚本中叫 sprite

  • Color:图片颜色

  • RaycastTarget:是否可以作为射线目标,后续点击、拖拽等事件需要使用

  • ImageType:显示模式

    • Simple:普通模式

    • Sliced:切片,需要图片九空格,要在组员层面处理

    • Tilled:平铺

    • Filled:填充

| 主要功能

  • Set Native Size:设置为图片的原始尺寸
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 如果需要用脚本操作 UI 相关的操作,必须引入 UI 的命名空间
using UnityEngine.UI;

public class L5_2Demo : MonoBehaviour
{
    private Image image;

    void Start()
    {
        image = GetComponent<Image>();
        image.color = Color.black;
    }
}

Text 组件

| 组件介绍

显示文本,如等级、属性值、角色名称等

| 常用属性

  1. Text:显示的文本内容

  2. Font:字体

  3. Font Style:字体样式,主要是加粗、斜体

  4. Font Size:字体大小

  5. Line Spacing:行间距

  6. RichText:富文本,Html经验者可尝试

  7. Color:字体颜色

  8. Raycast Target:是否作为射线检测的目标,也就是射线可以检测到,意味着后续是否可以点击等

| 对齐属性

  1. Alignment:文本的对齐方式

  2. Horizontal Oveflow:水平溢出

    1. Wrap:当达到水平边界,文本将自动换行

    2. Overflow:可以超出水平边界,继续显示

  3. Vertical Oveflow:垂直溢出

    1. Truncate:文本不显示超出垂直边界的部分

    2. Overflow:文本可以超出垂直边界,继续显示

  4. Best Fit:尽可能匹配边缘

    1. Min Size:字体的最小大小

    2. Max Size:字体的最大大小


Button 组件

| 构成

Button:Image、Button、Text

| 样式

  • Interactable:可交互的,就是 按钮是否有效

  • Transition:过渡方式,按钮一般分为几种状态,比如鼠标悬浮、点击、不可用

    • Target Graphic:按钮影响的 Image

    • Normal Color:常规

    • Highlighted Color:高亮、鼠标悬浮

    • Pressed Color:按下

    • Disabled Color:禁用

    • Fade Duration:颜色过渡时间

通常我们使用 WASD 或 上下左右 等方式选择按钮,Unity 的 UGUI 也具备这个功能并且设置起来十分方便

| 事件

OnClick():直接添加 or 自写函数

演示:

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

public class L5_4Demo : MonoBehaviour
{
    private Button button;

    private void Start()
    {
        button = GetComponent<Button>();
        button.onClick.AddListener(ButtonClick2);
    }
    public void ButtonClick2()
    {
        Debug.Log("ButtonClick2");
    }
    public void ButtonClick()
    {
        Debug.Log("ButtonClick");
    }
}

InputField 组件

| 结构

InputField: Image组件(背景图片)、InputField组件

Placeholder: Text组件(玩家完全没输入时显示内容)

Text: Text 组件实际输入的承载组件

| 输入类型

InputField 中 ContentType 可以设置玩家输入的类型,比如邮箱、密码等

| 事件

和 Button 类似

注意:如果需要手动获取 InputField 中玩家输入的值,要直接使用 InputField.text,而不要去查找子物体 Text 中的组件

演示:

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

public class L5_5Demo : MonoBehaviour
{
    private InputField inputField;
    void Start()
    {
        inputField = GetComponent<InputField>();
        //inputField.text = "666";
        //Debug.Log(inputField.text);

        inputField.onValueChanged.AddListener(OnValueChanged);
        inputField.onEndEdit.AddListener(OnEndEdit);
    }
    public void OnValueChanged(string value)
    {
        Debug.Log("OnValueChanged: "+value);
    }

    public void OnEndEdit(string value)
    {
        Debug.Log("OnEndEdit: "+value);
    }
}

Toggle 组件

| 基本使用

  • Toggle组件:

    • Background:Image组件(背景图)

    • Checkmark:Image组件(打勾)

    • Label:Text组件(文本)

| ToggleGroup

演示:

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

public class L5_6Demo : MonoBehaviour
{
    private Toggle toggle;
    void Start()
    {
        toggle = GetComponent<Toggle>();
        toggle.onValueChanged.AddListener(OnValueChanged);
    }
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log(toggle.isOn);
        }
    }
    public void OnValueChanged(bool bl)
    {
        Debug.Log("bl: " + bl);
    }
}

案例:注册与登录

| 介绍

注册: 玩家输入账号、密码、重复密码、性别等来完成注册,其中需要对密码与重复密码进行一致性校验

登录: 玩家输入账号、密码后和之前输入的账号密码等信息进行匹配;玩家输入有误时进行弹窗提示

| 分析

  • 主面板: 有两个按钮 - 注册 / 登录,点击后切换到对应面板

  • 注册面板:

    • 玩家输入账号、密码、重复密码、性别后点击注册,对密码与重复密码进行匹配

      • 输入正确:弹窗 “注册成功,请登录!”

      • 输入错误 - 账号与密码没输入:弹窗 “请输入账号或密码!”

      • 输入错误 - 密码与重复密码不一致:弹窗 “密码与重复密码不一致!”

    • 返回按钮:返回主面板

| 实现

L5_7MainPanel:

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

public class L5_7MainPanel : MonoBehaviour
{
    public static L5_7MainPanel Instance;
    private Button signUpButton;
    private Button loginButton;

    private void Awake()
    {
        Instance = this;
    }
    void Start()
    {
        signUpButton = transform.Find("SignUpButton").GetComponent<Button>();
        loginButton = transform.Find("LoginButton").GetComponent<Button>();

        signUpButton.onClick.AddListener(SignUpButtonClick);
        loginButton.onClick.AddListener(LoginButtonClick);
    }
    private void SignUpButtonClick()
    {
        // open sign up
        L5_7SignUpPanel.Instance.Show();
        gameObject.SetActive(false);
    }
    private void LoginButtonClick()
    {
        // open log in
        L5_7LoginPanel.Instance.Show();
        gameObject.SetActive(false);
    }
    public void Show()
    {
        gameObject.SetActive(true);
    }
}

L5_7FloatWindow:

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

public class L5_7FloatWindow : MonoBehaviour
{
    public static L5_7FloatWindow Instance;
    private Text infoText;
    private Button okButton;

    private void Awake()
    {
        Instance = this;
        infoText = transform.Find("Info").GetComponent<Text>();
        okButton = transform.Find("OKButton").GetComponent<Button>();
        okButton.onClick.AddListener(OKButtonClick);
        OKButtonClick();
    }

    public void ShowInfo(string info)
    {
        gameObject.SetActive(true);
        infoText.text = info;
    }

    private void OKButtonClick()
    {
        gameObject.SetActive(false);
    }
}

L5_7SignUpPanel:


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

public class L5_7SignUpPanel : MonoBehaviour
{
    public static L5_7SignUpPanel Instance;
    private InputField account;
    private InputField password;
    private InputField rePassword;
    private Toggle isMan;

    private Button returnButton;
    private Button okButten;

    private void Awake()
    {
        Instance = this;
        account = transform.Find("Account/InputField").GetComponent<InputField>();
        password = transform.Find("Password/InputField").GetComponent<InputField>();
        rePassword = transform.Find("RePassword/InputField").GetComponent<InputField>();
        isMan = transform.Find("GenderGroup/Male").GetComponent<Toggle>();

        returnButton = transform.Find("ReturnButton").GetComponent<Button>();
        okButten = transform.Find("OKButten").GetComponent<Button>();

        returnButton.onClick.AddListener(ReturnButtonClick);
        okButten.onClick.AddListener(OKButtenClick);

        gameObject.SetActive(false);
    }

    private void ReturnButtonClick()
    {
        // back Main
        L5_7MainPanel.Instance.Show();
        gameObject.SetActive(false);
    }

    private void OKButtenClick()
    {
        // login go
        if (string.IsNullOrEmpty(account.text) || string.IsNullOrEmpty(password.text) || string.IsNullOrEmpty(rePassword.text))
        {
            L5_7FloatWindow.Instance.ShowInfo("Please input account or password!");
        }
        else if (password.text != rePassword.text)
        {
            L5_7FloatWindow.Instance.ShowInfo("Password is not match!");
        }
        else
        {
            // The account does exist
            if (L5_7GameManager.Instance.GetUserInfo(account.text) != null )
            {
                L5_7FloatWindow.Instance.ShowInfo("Do not repeat sign up!");
            }
            else
            {
                L5_7UserInfo userInfo = new L5_7UserInfo(account.text, password.text, isMan.isOn);
                // save account
                L5_7GameManager.Instance.SaveUserInfo(userInfo);
                L5_7FloatWindow.Instance.ShowInfo("Success! Please log in!");
            }
        }
    }

    public void Show()
    {
        gameObject.SetActive(true);
        account.text = "";
        password.text = "";
        rePassword.text = "";
        isMan.isOn = true;
    }
}

L5_7LoginPanel:

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

public class L5_7LoginPanel : MonoBehaviour
{
    public static L5_7LoginPanel Instance;

    private InputField account;
    private InputField password;

    private Button returnButton;
    private Button okButten;

    private void Awake()
    {
        Instance = this;
        account = transform.Find("Account/InputField").GetComponent<InputField>();
        password = transform.Find("Password/InputField").GetComponent<InputField>();

        returnButton = transform.Find("ReturnButton").GetComponent<Button>();
        okButten = transform.Find("OKButten").GetComponent<Button>();

        returnButton.onClick.AddListener(ReturnButtonClick);
        okButten.onClick.AddListener(OKButtenClick);

        gameObject.SetActive(false);
    }

    private void ReturnButtonClick()
    {
        // back Main
        L5_7MainPanel.Instance.Show();
        gameObject.SetActive(false);
    }

    private void OKButtenClick()
    {
        if (string.IsNullOrEmpty(account.text) || string.IsNullOrEmpty(password.text))
        {
            L5_7FloatWindow.Instance.ShowInfo("Please input account or password!");
        }
        else
        {
            L5_7UserInfo userInfo = L5_7GameManager.Instance.GetUserInfo(account.text);
            if (userInfo == null)
            {
                L5_7FloatWindow.Instance.ShowInfo("The account does not exist!");
            }
            else if(userInfo.password != password.text)
            {
                L5_7FloatWindow.Instance.ShowInfo("account or password is wrong!");
            }
            else if(userInfo.password == password.text)
            {
                L5_7FloatWindow.Instance.ShowInfo("sign up Success!");
            }
        }
    }

    public void Show()
    {
        gameObject.SetActive(true);
        account.text = "";
        password.text = "";
    }
}

L5_7GameManager:

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

public class L5_7UserInfo
{
    public string account;
    public string password;
    public bool isMan;

    public L5_7UserInfo(string account, string password, bool isMan)
    {
        this.account = account;
        this.password = password;
        this.isMan = isMan;
    }
}

public class L5_7GameManager
{
    private static L5_7GameManager instance;

    // after sign up's account massage
    public List<L5_7UserInfo> UserInfos = new List<L5_7UserInfo>();

    public static L5_7GameManager Instance
    {
        get
        {
            if(instance == null) instance = new L5_7GameManager();
            return instance;
        }
    }

    public void SaveUserInfo(L5_7UserInfo userInfo)
    {
        UserInfos.Add(userInfo);
    }

    public L5_7UserInfo GetUserInfo(string userNamer)
    {
        for (int i = 0; i < UserInfos.Count; i++)
        {
            if(userNamer == UserInfos[i].account)
            {
                return UserInfos[i];
            }
        }
        return null;
    }
}

Slider 组件

| 功能

  • Slider:Slider组件

    • Background:Image组件(背景图)

    • Fill Area:填充区域

      • Fill:Image组件(填充物)
    • Handle Slider Area:触摸区域

      • Handle:Image组件(触摸物体实际图片)

演示:

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

public class L5_8Demo : MonoBehaviour
{
    private Slider slider;
    void Start()
    {
        slider = GetComponent<Slider>();

        slider.onValueChanged.AddListener(SliderOnValueChanged);
    }

    void SliderOnValueChanged(float value)
    {
        Debug.Log(value);
    }
}

ScrollBar 组件

| 结构

Scrollbar:Scrollbar 组件

Sliding Area:拖拽区域

Handle:Image组件(拖拽物体的实际显示)



👾森木清树👾

Unity Study