【2D轮转图】简单详细的2D轮转,并自动对齐最终人物,生成角色

1,制作显示形象的预制体,两层image,美观一些

2,制作一个image,就是效果里面的半透明灰色背景,在这里挂脚本

 代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using DG.Tweening;

public class RotationChart2D : MonoBehaviour,IDragHandler, IEndDragHandler
{
    public Image prefab;    //预制体
    public float max=1;     //缩放最大值
    public float min=0.5f;  //缩放最小值
    public int n;           //个数
    public float spacing = 100;//UI间距单位是像素 比较大

    public float cut = 100; //减速度
    float c;  
    float r;
    float ang;
    List<Image> list = new List<Image>();
    List<Transform> sortList = new List<Transform>();
    //拖动弧度
    float moveAng = 0;

    //角色
    private GameObject player;
    //雷达显示部分
    public GameObject show;
    void Start()
    {
        //周长=(宽+间距)*个数
        c = (prefab.rectTransform.rect.width + spacing) * n;
        //半径=周长/2π
        r = c / (2 * Mathf.PI);

        ang = 2 * Mathf.PI / n;
        //转动方法
        Move();

        //获取数据
        show.GetComponent<RadarMap3>().GetArr();

    }
    public void Move()
    {
        for (int i = 0; i < n; i++)
        {
            //判断集合中有就不创建,没有再创建
            if(list.Count<=i)
            {
                list.Add(Instantiate(prefab, transform));//添加图片
                list[i].transform.GetChild(0).GetComponent<Image>().sprite = Resources.Load<Sprite>("Image/image" + i);
                sortList.Add(list[i].transform);

            }

            float x = Mathf.Sin(i * ang+moveAng) * r;
            float z = Mathf.Cos(i * ang+moveAng) * r;
            //通过z 计算 近大远小
            //计算z 0-1的比值 和雷达图计算uv坐标相同
            float p = (z + r) / (2 * r);
            float scale = (max - min) * p + min;  //这是一个比值
            //float scale = min * (1 - p) + max * p;
            list[i].rectTransform.anchoredPosition = new Vector2(x, 0);
            list[i].transform.localScale = Vector3.one * scale;

           
        }
        //排序
        sortList.Sort((a, b) =>
        {

            if (a.localScale.x < b.localScale.x)
            {
                return -1;
            }
            else if (a.localScale.x == b.localScale.x)
            {
                return 0;
            }
            else
            {
                return 1;
            }

        });
        for (int i = 0; i < sortList.Count; i++)
        {
            sortList[i].SetSiblingIndex(i);
        }
    }
    // Update is called once per frame
    void Update()
    {
        
    }
    public void OnDrag(PointerEventData eventData)
    {
        //每帧拖动的距离
        float dis = eventData.delta.x;
        //通过距离计算弧度
        float dragAng = dis / r;

        moveAng += dragAng;
        //鼠标只要移动就会移动
        Move();
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        float speed = eventData.delta.x;
        float time = Mathf.Abs(speed) / cut;

        DOTween.To((a)=> 
        {
            //通过距离计算弧度
            float dragAng = a / r;
            moveAng += dragAng;
            //结束拖拽也会移动
            Move();

        },speed,0,time).OnComplete(()=> 
        { 
            //下标 获取图片的id
            Align(list.IndexOf(sortList[n - 1].GetComponent<Image>()));
        
        });
    }

    //对齐
    public void Align(int id)
    {
        //当前下标
        int index = list.IndexOf(sortList[n - 1].GetComponent<Image>());
        //指定下标与当前下标的间隔
        int sp = id - index;
        //计算另一个旋转方向需要的间隔
        int sp0 = n - Mathf.Abs(sp);
        //一个为顺时针 另一个必为逆时针 所以正负要注意
        sp0 = sp > 0?-sp0:sp0;
        //选择两个方向中   间隔较小的一方 去旋转
        int end = Mathf.Abs(sp) < Mathf.Abs(sp0) ? sp : sp0;
        //通过间隔计算弧度
        float spAng = end * ang;
        //弧度=asin(对边x/斜边r)
        //需要旋转的弧度=与中间偏差的弧度+间隔弧度
        float AlignAng = Mathf.Asin(sortList[n - 1].GetComponent<RectTransform>().anchoredPosition.x / r)+spAng;
       //距离=弧度*半径
        float AlugnDis = AlignAng * r;
        //时间
        float time = Mathf.Abs(AlugnDis)/cut;
        //自动对齐
        DOTween.To((a)=> 
        {
            moveAng = a;
            Move();
        },moveAng,moveAng-AlignAng,time).OnComplete(()=>  //生成角色
        {

            if (player != null)
            {
                Destroy(player);
            }
            player = Instantiate(Resources.Load<GameObject>("Player/" + id));
            player.transform.position = new Vector3(0.45f, -2, 0);
            player.transform.eulerAngles = new Vector3(0, 180, 0);
            show.GetComponent<RadarMap3>().Change(id);

        });
    }
}

参考参数:

这里的Show是雷达图,可以显示每个人的数据,我们下期再讲雷达图。

补充:SetSiblingIndex 设置创建的物体在你想要的位置

 3. 若是点击button 转到初始第一位

注意 这的“0” 就是传入参数 0  代表第一位初始角色

4:转动结束后,实例化对应角色

猜你喜欢

转载自blog.csdn.net/m0_74022070/article/details/130398501
2D