【Unity-小组件】简易收缩列表

出发点
        为了完成策划同学的一些简单动画需求,每次重复写简单动画得不偿失,所以将简单的收缩动画写成组件封装起来。
 动画效果:

        


给出c#代码
#if UNITY_EDITOR
using Sirenix.OdinInspector;
#endif
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

/// <summary>
/// 延展动画
/// </summary>
public class ExtendAnimComponent : MonoBehaviour
{
    /// <summary>
    /// 简易动画类型
    /// </summary>
    public enum EEasyAnimType
    {
        Left,
        Right,
        Top,
        Bottom,
        Custom
    }
    #region 事件区

#if UNITY_EDITOR
    [LabelText("动画播放时每帧回调")]
#endif
    public UnityEvent ExtendUpdateEvent = new();
    
    private event Action _ExtendChangeEvent;

    #endregion

    #region 属性区



    #endregion

    #region 变量区

    /// <summary>
    /// 延展对象
    /// </summary>
    public RectTransform extendRectTransform;

    /// <summary>
    /// 动画类型
    /// 向左收缩
    /// 向右收缩
    /// 向上收缩
    /// 向下收缩
    /// 自定义
    /// </summary>
    //[StringDropList("Left","Right","Top","Bottom","Custom")]
    public EEasyAnimType animationType;

    [SerializeField]
#if UNITY_EDITOR
    [Header("是否使用自定义收缩大小")]
#endif
    private bool _isUseCustomSize;

#if UNITY_EDITOR
    [ShowIf("@_isUseCustomSize == true")]
#endif
    public Vector2 customExtendSize;

    /// <summary>
    /// 是否为收紧状态
    /// </summary>
    [Header("是否为收紧状态")]
    public bool isContract;
    
    /// <summary>
    /// 是否每次激活都是收紧状态
    /// </summary>
    [SerializeField]
    [Header("是否每次激活都是收紧状态")]
    private bool _enableContract;

    [Header("控制伸缩的toggle")]
    [Tooltip("处于展开时isOn为true,反之为false")]
    public Toggle toggle;

    /// <summary>
    /// 扩展栏原大小
    /// </summary>
    private Vector2 _sourceSize;

    private Vector2 _targetSize;

    private Coroutine _coroutine;
    
    #endregion

    #region 函数区

    //--------------------Public 公有函数--------------------//

    /// <summary>
    /// 注册收缩延展改变时的回调
    /// </summary>
    /// <param name="changeAction"> 回调方法 </param>
    public void RegisterExtendChangeAction(Action changeAction)
    {
        if (changeAction == null)
        {
            return;
        }

        _ExtendChangeEvent -= changeAction;
        _ExtendChangeEvent += changeAction;
    }

    /// <summary>
    /// 重置原始大小
    /// </summary>
    /// <param name="rectTransform"></param>
    public void ResetSourceSizeDelta(RectTransform rectTransform)
    {
        _sourceSize = rectTransform.sizeDelta;

        if (extendRectTransform)
        {
            extendRectTransform.sizeDelta = isContract ? _GetTargetSize() : _sourceSize;
        }
    }
    
    /// <summary>
    /// 播放动画
    /// </summary>
    public void PlayAnim()
    {
        if (_coroutine != null)
        {
            StopCoroutine(_coroutine);
        }
        if (gameObject.activeSelf)
        {
            _coroutine = StartCoroutine(ExtendAnim());
        }
        else
        {
            SetSize();
        }
    }

    //--------------------Protect 保护函数--------------------//

    protected virtual void Awake()
    {
        if (_isUseCustomSize)
        {
            _targetSize = customExtendSize;
        }
        _sourceSize = extendRectTransform.sizeDelta;
    }

    protected virtual void OnEnable()
    {
        Vector2 targetSizeDelta = _sourceSize;
        if (_enableContract || isContract)
        {
            if (_enableContract)
            {
                isContract = true;
            }

            if (toggle != null)
            {
                toggle.SetIsOnWithoutNotify(!isContract);
            }

            targetSizeDelta = _GetTargetSize();
        }
        
        extendRectTransform.sizeDelta = targetSizeDelta;
    }
    
#if UNITY_EDITOR
    private void OnValidate()
    {
        _InitExtendRectPivot();
    }
#endif

    //--------------------Private 私有函数--------------------//

    /// <summary>
    /// 右上方扩展按钮点击效果
    /// </summary>
    /// <returns></returns>
    private IEnumerator ExtendAnim()
    {
        Vector2 targetSize = Vector2.zero;
    
        _ExtendChangeEvent?.Invoke();
        
        if (isContract)
        {
            targetSize = _sourceSize;
        }
        else
        {
            targetSize = _GetTargetSize();
        }
    
        Vector2 diffVector = targetSize -  extendRectTransform.sizeDelta;
        
        isContract = !isContract;
        
        while (true)
        {
            extendRectTransform.sizeDelta += diffVector * (Time.fixedDeltaTime * 10f);
            yield return new WaitForSecondsRealtime(Time.fixedDeltaTime);
            int axisIndex = animationType == EEasyAnimType.Left || animationType == EEasyAnimType.Right ? 0 : 1;
            ExtendUpdateEvent?.Invoke();
            if (Mathf.Abs((extendRectTransform.sizeDelta - targetSize)[axisIndex]) < 0.1f)
            {
                break;
            }
        }
    }

    public void SetSize()
    {
        Vector2 targetSize = Vector2.zero;

        _ExtendChangeEvent?.Invoke();

        if (isContract)
        {
            targetSize = _sourceSize;
        }
        else
        {
            targetSize = _GetTargetSize();
        }
        extendRectTransform.sizeDelta = targetSize;
        isContract = !isContract;
    }


    /// <summary>
    /// 获取目标size
    /// </summary>
    /// <returns></returns>
    private Vector2 _GetTargetSize()
    {
        Vector2 targetSize = _targetSize;
        if (_isUseCustomSize)
        {
            return targetSize;
        }
        switch (animationType)
        {
            case EEasyAnimType.Top:
            case EEasyAnimType.Bottom:
                targetSize = new Vector2(_sourceSize.x, 0);
                break;
            case EEasyAnimType.Left:
            case EEasyAnimType.Right:
                targetSize = new Vector2(0, _sourceSize.y);
                break;
        }

        return targetSize;
    }

    /// <summary>
    /// 初始化中心点
    /// </summary>
    private void _InitExtendRectPivot()
    {
        switch (animationType)
        {
            case EEasyAnimType.Left:
                extendRectTransform.pivot = new Vector2(0, 0.5f);
                break;
            case EEasyAnimType.Right:
                extendRectTransform.pivot = new Vector2(1, 0.5f);
                break;
            case EEasyAnimType.Top:
                extendRectTransform.pivot = new Vector2(0.5f, 1f);
                break;
            case EEasyAnimType.Bottom:
                extendRectTransform.pivot = new Vector2(0.5f, 0f);
                break;
        }
    }

    public void SetSourceSize(Vector2 size)
    {
        _sourceSize = size;
    }

    public void SetCustomExtendSize(Vector2 size)
    {
        customExtendSize = size;
        if (_isUseCustomSize)
        {
            _targetSize = customExtendSize;
        }
    }
    #endregion
}

组件说明

        

  •  extendRectTransform:动画所控制的收缩rect
  • animationType:你的收缩类型-》向上,向下,向左,向右 or 自定义
  • isUseCustomSize:是否使用自定义的收缩大小,在git图中,左边的就是自定义的收缩大小,默认是吧scale收缩为0
  • enableContract:默认状态是否是收缩状态。
  • enableContract:每次激活是否是收紧状态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值