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

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

unity c# 制作英雄 卡牌 循环滚动列表_第1张图片
我们将卡牌之间 的间隔变大,则可以看到 下面的UIunity c# 制作英雄 卡牌 循环滚动列表_第2张图片

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

unity c# 制作英雄 卡牌 循环滚动列表_第3张图片

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

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

unity c# 制作英雄 卡牌 循环滚动列表_第5张图片

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

我这里 百度截图了 10张图,将就着用。unity c# 制作英雄 卡牌 循环滚动列表_第6张图片
先初始化这 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;
        }
    }

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

unity c# 制作英雄 卡牌 循环滚动列表_第7张图片

接下来处理 卡牌 :


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 也就是拖拽的 值传递到 父节点的脚本中。
unity c# 制作英雄 卡牌 循环滚动列表_第8张图片
unity c# 制作英雄 卡牌 循环滚动列表_第9张图片
unity c# 制作英雄 卡牌 循环滚动列表_第10张图片
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 下载

你可能感兴趣的:(笔记)