unity c# 制作英雄 卡牌 循环滚动列表

    技术2022-07-20  100

    unity c# 制作英雄 卡牌 循环滚动列表

    我们将卡牌之间 的间隔变大,则可以看到 下面的UI

    首先,我们 想做一个滚动列表,这就像在 x轴 和Z 轴上的 一个循环的椭圆

    ##如果我们将卡牌平均分布在这个椭圆上。那么每个卡牌占这个 椭圆 整个圆周 角度一定的 比例。我们定这个比例 为 radio ,radio 的值 从 0 ~ 1 ,0和1 的点重合。 现在大家 清除 我们卡牌 是怎么 排布的了吧。 我们 需要做的点有四个: 1.将 卡牌 排布在这个椭圆上。 2. 根据 radio 去 设置 不同位置的卡牌的 缩放。 3. 为了看起来有层次感,我们需要设置 卡牌的 层级。 4. 最后就是 给卡牌添加 拖拽的监听。

    那么现在第一步骤: 在 unity UI 上添加一个 节点,用来放置我们的卡牌。 在UI 上加个 空的 组件。作为父节点。

    然后 添加 C# 脚本,添加到该组件上。

    我这里 百度截图了 10张图,将就着用。 先初始化这 10张卡牌

    private GameObject CreateTempate() { GameObject temp = new GameObject("Template"); temp.AddComponent<PageItem>(); temp.AddComponent<RectTransform>().sizeDelta = ItemSize; temp.AddComponent<Image>(); return temp; } private void CreateItem() { GameObject temp = CreateTempate(); for (int i = 0; i < SpriteList.Count; i++) { PageItem item = Instantiate(temp).GetComponent<PageItem>(); item.Index = i; item.SetImage(SpriteList[i]); item.SetParent(transform); item.AddEventlistenr(change); ItemList.Add(item); } }

    我们 在这个椭圆上 平均分布 这些卡牌,则 均分的 系数 是 radio = 1/10,十张卡牌均分;

    private void CaculateData() { float length = (ItemSize.x + OffSetX) * 6; float radio = 1.0f / SpriteList.Count; float tempRadio = 0f; for (int i = 0; i < SpriteList.Count; i++) { ItemPosData pos = new ItemPosData(); ItemIdData itemId = new ItemIdData(); itemId.Id = i; pos.X = GetX(tempRadio, length); pos.ScareTimes = GetScaraTimes(tempRadio, ScareMax, ScareMin); tempRadio += radio; pos.Order = i; ItemPosList.Add(pos); itemIdList.Add(itemId); } itemIdList = itemIdList.OrderBy(u => ItemPosList[u.Id].ScareTimes).ToList(); for (int i = 0; i < itemIdList.Count; i++) //根据缩放有小到大,排列了id列表 { int id = itemIdList[i].Id; ItemPosList[id].Order = i; } for (int i = 0; i < ItemPosList.Count; i++) { ItemList[i].SetPositon(ItemPosList[i]); } }

    length 是我们自己定义 滚动列表的宽度,很重要的一点,Z 轴 左右两边 的 卡牌坐标是是对称的。 我们根据 radio 和宽度 计算出 卡牌的 X 坐标。

    private float GetX(float radio, float length) { if (radio < 0 || radio > 1) { Debug.Log("系数错误"); return 0; } if (radio >= 0 && radio <= 0.25f) { return radio * length; } else if (radio > 0.25 && radio < 0.75f) { return (0.5f - radio) * length; } else { return (radio - 1f) * length; } }

    同样的,卡牌的缩放,也是 左右对称的。

    private float GetScaraTimes(float radio, float scareMax, float scareMin) { float scareSub = scareMax - scareMin; if (radio < 0f || radio > 1f) { Debug.Log("系数错误"); return 0; } if (radio == 0 || radio == 1f) { return scareSub; } if (radio > 0 && radio <= 0.5f) { return (1 - radio) * scareSub;//0.5 ~ 1 } else { return radio * scareSub; } }

    这时候的 卡牌是没有层级的

    接下来处理 卡牌 :

    using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using UnityEngine.UI; using UnityEngine.EventSystems; using System; public class PageItem : MonoBehaviour,IDragHandler,IEndDragHandler { private float X; private int index; private float ScareTimes; private float offX = 0; private Action<float> MoveAction; private Image myImage; private Image MyImage { get { if (myImage == null) myImage = GetComponent<Image>(); return myImage; } } private RectTransform myRect; private RectTransform MyRect { get { if (myRect == null) myRect = GetComponent<RectTransform>(); return myRect; } } public int Index { get=> index; set => index = value; } void Start() { } public void SetParent(Transform parent) { transform.SetParent(parent); } public void SetPositon(ItemPosData posData) { MyRect.DOAnchorPos(Vector2.right * posData.X, 1.0f); MyRect.DOScale(Vector2.one * posData.ScareTimes, 1.0f); StartCoroutine(wait(posData.Order)); } IEnumerator wait(int order) { yield return new WaitForSeconds(0.5f); //transform.SetSiblingIndex(order); } public void SetImage(Sprite sprite) { MyImage.sprite = sprite; } public void AddEventlistenr(Action<float> move) { MoveAction = move; } public void OnDrag(PointerEventData eventData) { offX += eventData.delta.x; //Debug.Log("offX=========" + offX); } public void OnEndDrag(PointerEventData eventData) { MoveAction(offX); offX = 0; } }

    item 中 我们 重点 就是 添加可 两个 拖拽接口: IDragHandler,IEndDragHandler 这是我们能让 卡牌滚动的重点。

    通过委托,我们将 offX 也就是拖拽的 值传递到 父节点的脚本中。 item.AddEventlistenr(change);

    我们 通过 计算好的 位置 和缩放值 的列表。 去给 item 重新设置 位置 和 缩放,就产生了滚动的效果。

    private void change(float offX) { int symbol = 0; symbol = offX > 0 ? 1 : -1; rotateItem(symbol); } private void rotateItem(int symbol) { int allNums = itemIdList.Count; int lens = allNums - 1; int maxValues = lens; for (int i = 0; i < ItemPosList.Count; i++) { int index = ItemList[i].Index; if (symbol < 0) { if (index == 0) { index = maxValues; } else { index = index + symbol; } } else { if (index == maxValues) { index = 0; } else { index = index + symbol; } } ItemList[i].Index = index; } for (int i = 0; i < allNums; i++) { int index = ItemList[i].Index; ItemList[i].SetPositon(ItemPosList[index]); } }

    这里主要 要理解 的还是位置的重置。

    链接: https://pan.baidu.com/s/1dynUHQYCCevMUW8qFlRM-Q 提取码: r59t demo 下载

    Processed: 0.012, SQL: 10