做了部分优化及功能添加
效果:
/*******************************************************************************
* 版本声明:v1.1.0
* 类 名 称:UIRotationManager
* 创建日期:2020-05-19 15:52:49
* 作者名称:末零
* 功能描述:UGUI轮播
* 修改记录:
* v1.0.0 完成左右一位的位移(暂时不支持多位移动)
* v1.0.1 优化排列时位置的计算,解决遮盖问题
* v1.0.2 解决SiblingIndex设置后出现外侧遮盖内侧的问题
* v1.1.0 添加显示数量控制
*
******************************************************************************/
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
namespace LastZero
{
/// <summary>
/// 状态枚举
/// </summary>
public enum RotationState
{
Rotating,
Stop
}
/// <summary>
/// 轮播
/// </summary>
public class UIRotationManager : MonoBehaviour
{
public int indexCenter = 0;//初始时,位于中间位置的对象ID
public float cellWidth = 100;//宽度
public float scaleMultiple = 1;//缩放倍数
public float speed = 5;//轮播速度
public int displayNumber = 0;//要显示的轮播物体个数
private List<UIRotationItem> items = new List<UIRotationItem>();//所有子物体(要轮播的)
private List<int> relativePosition = new List<int>();//相对位置
private int indexHalf;//轮播对象数量的中值
private List<int> order = new List<int>();//顺序
private RotationState state = RotationState.Stop;//状态
private void Awake()
{
items.AddRange(transform.GetComponentsInChildren<UIRotationItem>());
}
private void Start()
{
Init();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
DoRotateItems(1);
}
if (Input.GetKeyDown(KeyCode.RightArrow))
{
DoRotateItems(-1);
}
}
/// <summary>
/// 初始化
/// </summary>
private void Init()
{
displayNumber = displayNumber == 0 ? items.Count : displayNumber;
indexHalf = (items.Count - 1) / 2;
for (int i = 0; i < items.Count; i++)
{
int target = i - indexHalf + indexCenter;
target = target < 0 ? target + items.Count : target >= items.Count ? target - items.Count : target;
items[i] = transform.GetChild(target).GetComponent<UIRotationItem>();
relativePosition.Add(i - indexHalf);
}
DoRotateItems();
}
/// <summary>
/// 获取当前状态
/// </summary>
/// <returns></returns>
public RotationState GetState()
{
return state;
}
/// <summary>
/// 轮播
/// </summary>
/// <param name="value"></param>
public void DoRotateItems(int value = 0)
{
if (state == RotationState.Rotating) return;
order.Clear();
for (int i = 0; i < items.Count; i++)
{
int target = i + value;
if (target < 0)
{
target += items.Count;
}
else if (target >= items.Count)
{
target -= items.Count;
}
order.Add(target);
float positionX = 0f;
for (int j = 1; j <= Mathf.Abs(relativePosition[target]); j++)
{
positionX += cellWidth * Mathf.Pow(scaleMultiple, j) * (relativePosition[target] == 0 ? 0 : Mathf.Abs(relativePosition[target]) / relativePosition[target]);
}
// 一半的位置 - 要显示个个数的一半 -> 左侧 半数 + 要显示的个数减去左侧已显示的
if((target < (indexHalf - (displayNumber - 1) / 2)) || target > (indexHalf + displayNumber - (displayNumber - 1) / 2 - 1))//隐藏掉左右两端不该显示的
{
items[i].LocalScale = 0;
}
else if ((target == (indexHalf - (displayNumber - 1) / 2) && value > 0) || (target == (indexHalf + displayNumber - (displayNumber - 1) / 2 - 1) && value < 0))
{
int indexI = i;
int indexTarget = target;
items[i].transform.DOScale(0.01f, Mathf.Abs(value) / speed * 0.5f).OnComplete(() =>
{
items[indexI].LocalPositionX = positionX;//relativePosition[indexTarget] * cellWidth * Mathf.Pow(scaleMultiple, Mathf.Abs(relativePosition[indexTarget]));
items[indexI].transform.DOScale(Mathf.Pow(scaleMultiple, Mathf.Abs(relativePosition[indexTarget])), Mathf.Abs(value) / speed * 0.5f).SetEase(Ease.Linear);
});
}
else
{
items[i].transform.DOLocalMoveX(positionX, Mathf.Abs(value) / speed).SetEase(Ease.Linear);
items[i].transform.DOScale(Mathf.Pow(scaleMultiple, Mathf.Abs(relativePosition[target])), Mathf.Abs(value) / speed).OnComplete(() =>
{
state = RotationState.Stop;
}).SetEase(Ease.Linear);
}
}
StartCoroutine(CallBack(Mathf.Abs(value)));
state = RotationState.Rotating;
}
/// <summary>
/// 回调(单次轮播进行到一半时,重置List、改变SiblingIndex)
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
private System.Collections.IEnumerator CallBack(int time)
{
yield return new WaitForSeconds(time * 0.5f / speed);
UIRotationItem[] newItems = new UIRotationItem[items.Count];
for (int i = 0; i < items.Count; i++)
{
newItems[order[i]] = items[i];
}
items.Clear();
items.AddRange(newItems);
ChangeSiblingIndex();
}
/// <summary>
/// 改变SiblingIndex
/// </summary>
private void ChangeSiblingIndex()
{
for (int i = 0; i < items.Count; i++)
{
int index;
index = relativePosition[i] > 0 ? items.Count - 1 - relativePosition[i] * 2 + 1 : items.Count - 1 + relativePosition[i] * 2;
items[i].SiblingIndex = index;
}
}
}
}