Unity平面轮转图

之前提及的轮转图是在3D空间内利用z轴作为深度信息实现的,但是在2D空间内只有x,z,缺少了z轴.所以利用z轴进行场景伸缩的部分更改为使用UI上的Scale,更改缩放值实现。与3D相比,2D更多利用了UGUI自带的事件系统,代码也更简洁,3D上也可以使用事件系统实现。
定义部分如下

/*
	Button和Inputfield用于实现特别效果
	num表示总数量
	image为生成的预制体
	Max和Min为最大最小缩放值
	des则是之后Dottween效果的减速度
	*/
	public Button enter;
    public InputField inputField;

    public int num = 14;
    public Image prefeb;

    public float Max = 1;
    public float Min = 0.5f;
    public float des = 10; //减速度\
	
	/*
	周长
	半径
	弧度
	总移动幅度
	*/
    float l;
    float r;
    float ang;
    float allang = 0; //总移动幅度
    List<GameObject> RoleList = new List<GameObject>();
    List<Transform> RoleTran = new List<Transform>();

初始化 确定半径 周长 和弧度 开始实现

		l = num * prefeb.rectTransform.sizeDelta.x;
        r = l / (2 * Mathf.PI);
        ang = 2 * Mathf.PI / num;
        Move();

Move函数内存放了初始化预制体和移动的位置,开始是 allang总幅度为0,所以不移动

{
    
    
        for (int i = 0; i < num; i++)
        {
    
    
            if (RoleList.Count <= i)
            {
    
    
                RoleList.Add(Instantiate(prefeb.gameObject, transform));
                RoleTran.Add(RoleList[i].transform);
                RoleList[i].GetComponentInChildren<Text>().text = i.ToString();
            }
            
			//计算
			 
            float x = Mathf.Sin(i * ang + allang) * r * 2;
            float z = Mathf.Cos(i * ang + allang) * r * 2;

            float p = (z + r) / (r + r);
            float scale = Max * (1 - p) + Min * p; //缩放比
            RoleList[i].transform.localPosition = new Vector3(x, 0, 0);
            RoleList[i].transform.localScale = Vector3.one * scale;
        }
        //Sort函数负责排序
        Sort();
    }

Sort排序函数中使用了Dotween,也可以参考之前3D轮转图部分的自制Dotween可互通

{
    
    
//由于没有Z轴,所以前后顺序需要依靠缩放值以及渲染排序实现
        RoleTran.Sort((a, b) =>
        {
    
    
        //判断 2个图片的z轴哪一个更近
            if (a.lossyScale.z < b.lossyScale.z)
            {
    
    
                return -1;
            }
            else if (a.lossyScale.z > b.lossyScale.z)
            {
    
    
                return 1;
            }
            else
            {
    
    
                return 0;
            }
        });
		//循环添加进队列,进行渲染排序
        for (int i = 0; i < RoleTran.Count; i++)
        {
    
    
            RoleTran[i].SetSiblingIndex(i);
        }
    }

接下来使用拖拽事件,跳过BeginDrag的逻辑

	//拖拽中持续调用移动脚本
public void OnDrag(PointerEventData eventData)
    {
    
    
        allang -= eventData.delta.x / r;
        Move();
    }
//拖拽结束后确定位置,并判断对其以及缓动效果
    public void OnEndDrag(PointerEventData eventData)
    {
    
    
        float dis = eventData.delta.x / r;
        float time = Mathf.Abs(dis / des);
        DOTween.To((a) =>
        {
    
    
            allang -= a / r;
            Move();
        }, dis, 0, time).OnComplete(() =>
        {
    
    
            float moveang = Mathf.Asin(RoleTran[num - 1].localPosition.x / r);
            float moveTime = Mathf.Abs(dis / des);
            DOTween.To((b) =>
            {
    
    
                allang = b;
                Move();
            }, allang, allang + moveang, moveTime).OnComplete(() =>
            {
    
     });
        });
        DOTween.To((a) =>
        {
    
    
            allang -= a / r;
            Move();
        }, dis, 0, time);
    }

这是额外的Button和Inputfield使用,在Input里输入点击Button使用,跳转到对应图片,也可以单独设置Button进行固定位置的跳转

n0到n4的引用是用于判断最短路径,从而避免绕转一圈的效果

enter.onClick.AddListener(() =>
        {
    
    
            print(inputField.text);
            //前往位置
            int next = int.Parse(inputField.text);
            Sort();
            //当前位置
            int id = RoleList.IndexOf(RoleTran[num - 1].gameObject);

            /*
            初始值
            初始反值
            反值的方向
            取较短方向
            */
            int n0 = id - next;
            int n1 = num - Mathf.Abs(n0);
            int n2 = n0 > 0 ? -n1 : n1;
            int n3 = Mathf.Abs(n0)<Mathf.Abs(n2)? n0:n2;

            //(id - next)

            float moveang = Mathf.Asin(RoleTran[num - 1].localPosition.x / r) + n3 * ang;
            float moveTime = Mathf.Abs(moveang / des);
            dt0 = DT.To((b) =>
            {
    
    
                allang = b;
                Move();
            }, allang, allang + moveang, moveTime).OnComplete(() =>
            {
    
    

            });

        });

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_57252175/article/details/132328148