Unity3D 从 0 打造一个 NiceToggle 组件

目标

本文将从 0 教你如何打造一个 Unity 的组件,来创建属于你的 UGUI~
效果图在这里:


Unity3D 从 0 打造一个 NiceToggle 组件_第1张图片
TogglePrefer.gif

动起来

如果是你想要的效果,那么跟我一起动起来,如果不是请点击右上角~
本文的项目已上传 github 可以直接使用 Unity 打开使用,不想看教程,代码一样说明一切。
如要代码请点击这里。

创建 Canvas

所有的 UI 空间都需要在 Canvas 下进行布局,当然这是废话。


Unity3D 从 0 打造一个 NiceToggle 组件_第2张图片
image.png

所有的 UI 都会出现在摄像机面前了。

创建一个 Panel

对这里创建一个 Panel,来放下我们所有的组件,毕竟要手写一个 Toggle。这里起名叫做 NiceToggle。
大小设置为 200*70 。按照你的需求来。


Unity3D 从 0 打造一个 NiceToggle 组件_第3张图片
image.png

现在我们的组件是这样的结构。


Unity3D 从 0 打造一个 NiceToggle 组件_第4张图片
image.png

这是最基础的东西,下面就来加快速度了。

创建属于你的背景、滑块、ON文字、OFF 文字、需要相应的 Button

我们这里使用 Button 来响应用户的点击,当然你也可以用别的相应点击效果。

  • 背景是 Image 组件,起名为 ToggleBg。
  • 滑块是 Image 组件,起名为 Handle。
  • ON 是 Text 组件,起名 ON。
  • OFF 是 Text 组件,起名 OFF。
  • Button 是 Button 组件,起名 ToggleButton。

我们现在 Screen 是现在这样。


Unity3D 从 0 打造一个 NiceToggle 组件_第5张图片
image.png

要把所有的组件组合起来,所以需要一些资源文件,在项目中你都可以得到这些资源文件,首先是背景,我这里叫 Toggle_bg,大概是这个样子。


Unity3D 从 0 打造一个 NiceToggle 组件_第6张图片
Toggle_bg

其次是我的滑块背景,起名 Handle,大概是这个样子。


Unity3D 从 0 打造一个 NiceToggle 组件_第7张图片
Handle

放进 Unity 项目的时候要做这样的处理,这样做 Slice 的属性设置的时候,就不会不会出现圆角的拉伸情况,新技能赶紧 Get。
Unity3D 从 0 打造一个 NiceToggle 组件_第8张图片
image.png

将我们的格式编程 Sprite,选择 Sprite Editor。


Unity3D 从 0 打造一个 NiceToggle 组件_第9张图片
image.png

这样处理以后,无论你怎么拉伸就只会拉伸绿色框框内部的部分。
当然 Toggle_bg做相同处理,我把参数放在下面。
Unity3D 从 0 打造一个 NiceToggle 组件_第10张图片
image.png

两个其实很像~~。

制作我们的 Toggle

ToggleBg 参数如下图:

Unity3D 从 0 打造一个 NiceToggle 组件_第11张图片
image.png

Handle 参数如下图:
Unity3D 从 0 打造一个 NiceToggle 组件_第12张图片
image.png

ON 参数如下图:
Unity3D 从 0 打造一个 NiceToggle 组件_第13张图片
image.png

OFF 参数如下图:
Unity3D 从 0 打造一个 NiceToggle 组件_第14张图片
image.png

注意:ON 与 OFF 需要添加 Canvas Group,如果你想让我们 Toggle 更 Nice 的话。(调整透明度)
Button 参数如下图:
Unity3D 从 0 打造一个 NiceToggle 组件_第15张图片
image.png

OnClick 的函数等下说,如果你上面的步骤做好之后,你会得到一个这个。
Unity3D 从 0 打造一个 NiceToggle 组件_第16张图片
image.png

是不是很棒呢?那我们赶紧让他动起来。

编写 ToggleController 脚本

给 NiceToggle 添加脚本,取名 ToggleController。


Unity3D 从 0 打造一个 NiceToggle 组件_第17张图片
image.png

编写如下代码:

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

public class ToggleController : MonoBehaviour
{
    public bool isOn;
    public bool isEnable = true;

    public Color onColorBg;
    public Color offColorBg;
    public Color NoEnableBg;

    public Image toggleBgImage;
    public RectTransform toggle;

    public GameObject handle;
    private RectTransform handleTransform;


    public Button SwitchButton;

    private float handleSize;
    private float onPosX;
    private float offPosX;

    public float handleOffset;

    public GameObject onIcon;
    public GameObject offIcon;


    public float speed;
    static float t = 0.0f;

    private bool switching = false;


    void Awake()
    {
        handleTransform = handle.GetComponent();
        RectTransform handleRect = handle.GetComponent();
        handleSize = handleRect.sizeDelta.x;
        float toggleSizeX = toggle.sizeDelta.x;
        onPosX = (toggleSizeX / 2) - (handleSize / 2) - handleOffset;
        offPosX = onPosX * -1;
    }

    void Start()
    {
        if (isOn)
        {
            toggleBgImage.color = onColorBg;
            handleTransform.localPosition = new Vector3(onPosX, 0f, 0f);
            onIcon.gameObject.SetActive(true);
            offIcon.gameObject.SetActive(false);
            DOTweenTransparency(onIcon, 0f, 1f);
            DOTweenTransparency(offIcon, 1f, 0f);
        }
        else
        {
            toggleBgImage.color = offColorBg;
            handleTransform.localPosition = new Vector3(offPosX, 0f, 0f);
            onIcon.gameObject.SetActive(false);
            offIcon.gameObject.SetActive(true);
            DOTweenTransparency(onIcon, 1f, 0f);
            DOTweenTransparency(offIcon, 0f, 1f);
        }
    }

    void Update()
    {
        if (isEnable)
        {
            if (switching)
            {
                Toggle(isOn);
            }
        }
        else
        {
            toggleBgImage.color = NoEnableBg;
            onIcon.gameObject.SetActive(false);
            offIcon.gameObject.SetActive(true);
        }
    }

    public void DoYourStaff()
    {
        Debug.Log(isOn);
    }

    public void Switching()
    {
        if (isEnable)
        {
            switching = true;
        }
    }

    public void Toggle(bool toggleStatus)
    {
        if ((offIcon != null) && ((onIcon != null) && (!onIcon.active || !offIcon.active)))
        {
            onIcon.SetActive(true);
            offIcon.SetActive(true);
        }

        if (toggleStatus)
        {
            StopDOTweenSwitching();
            DOTweenSmoothColor(offColorBg);
            DOTweenTransparency(onIcon, 1f, 0f);
            DOTweenTransparency(offIcon, 0f, 1f);
            DOTweenSmoothMove(onPosX, offPosX);
        }
        else
        {
            StopDOTweenSwitching();
            DOTweenSmoothColor(onColorBg);
            DOTweenTransparency(onIcon, 0f, 1f);
            DOTweenTransparency(offIcon, 1f, 0f);
            DOTweenSmoothMove(offPosX, onPosX);
        }
    }

    void DOTweenSmoothMove(float startPosX, float endPosX)
    {
        DOTween.To(
            () => handleTransform.localPosition,
            x => handleTransform.localPosition = x,
            new Vector3((endPosX - startPosX) / 2, 0f, 0f),
            0.4f
        ).SetEase(Ease.OutQuad);
    }

    void DOTweenSmoothColor(Color endCol)
    {
        DOTween.To(
            () => toggleBgImage.color,
            x => toggleBgImage.color = x,
            endCol,
            0.4f
        ).SetEase(Ease.OutQuad);
    }

    void DOTweenTransparency(GameObject alphaObj, float startAlpha, float endAlpha)
    {
        CanvasGroup alphaVal;
        alphaVal = alphaObj.gameObject.GetComponent();
        DOTween.To(() => alphaVal.alpha, x => alphaVal.alpha = x, endAlpha, 0.4f);
    }

    void StopDOTweenSwitching()
    {
        switching = false;
        switch (isOn)
        {
            case true:
                isOn = false;
                DoYourStaff();
                break;

            case false:
                isOn = true;
                DoYourStaff();
                break;
        }
    }

}

请在 DoYourStaff() 中填写你的业务逻辑,这里使用的 DOTween 的数值线性变化,DOTween 的文档 下一篇文章会单独介绍这个的使用。再把所有的控件挂在到 Controller 上就可以达到文章开头的效果啦,试一下吧。

Unity3D 从 0 打造一个 NiceToggle 组件_第18张图片
image.png

你可能感兴趣的:(Unity3D 从 0 打造一个 NiceToggle 组件)