出发点:
为了完成策划同学的一些简单动画需求,每次重复写简单动画得不偿失,所以将简单的收缩动画写成组件封装起来。
动画效果:
给出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:每次激活是否是收紧状态