3d轮转图 俩个脚本  第一个挂空物体上  第二个挂在生成物上

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

public class RotationChart : MonoBehaviour
{
    public int n;//个数
    public float spacing;//间距
    float c;//周长
    float r;//半径
    float ang;//每个角的弧度
    float moveAng = 0;//移动的弧度
    List<GameObject> list = new List<GameObject>();
    List<Transform> sortList = new List<Transform>();
    public RadarMap radar;
    // Start is called before the first frame update
    void Start()
    {
        //计算周长=(人的宽+间距)*个数
        c = (1 + spacing) * n;
        //计算半径=周长/圆的弧度
        r = c / (2 * Mathf.PI);
        //计算每个角的弧度
        ang = 2 * Mathf.PI / n;

        //创建人
        for (int i = 0; i < n; i++)
        {
            list.Add(Instantiate(Resources.Load<GameObject>("Sphere"), transform));
            float x = Mathf.Sin(i * ang) * r;
            float z = Mathf.Cos(i * ang) * r;
            list[i].transform.localPosition = new Vector3(x, 0, z);
            list[i].AddComponent<PlayerMove>();
            sortList.Add(list[i].transform);
        }
    }

    public void Move(float dis)
    {
        //移动的弧度= 距离/半径
        moveAng += dis / r;
        for (int i = 0; i < list.Count; i++)
        {
            float x = Mathf.Sin(i * ang + moveAng) * r;
            float z = Mathf.Cos(i * ang + moveAng) * r;
            list[i].transform.localPosition = new Vector3(x, 0, z);
        }
    }

    //惯性,惯性的初速度就是最后一帧移动的距离
    public void Inertia(float endspeed)
    {
        //注意距离有正负,时间没有,所有求时间要用绝对值
        //计算时间=初速度/衰减速度
        float time = Mathf.Abs(endspeed) / 5;
        DOTween.To((float a) =>
        {
            Move(a);
        }, endspeed, 0, time).OnComplete(() =>
        {
            //惯性结束之后调用对齐
            Align();
        });
    }

    //对齐
    public void Align()
    {
        sortList.Sort((a, b) =>
        {
            if (a.localPosition.z < b.localPosition.z)
            {
                return 1;
            }
            else if (a.localPosition.z == b.localPosition.z)
            {
                return 0;
            }
            else
            {
                return -1;
            }

        });
        float AlignAng = Mathf.Atan(sortList[0].localPosition.x / sortList[0].localPosition.z);
        float AlignDis = AlignAng * r;
        float time = Mathf.Abs(AlignDis) / 5;
        DOTween.To((float a) =>
        {
            for (int i = 0; i < list.Count; i++)
            {
                float x = Mathf.Sin(i * ang + a) * r;
                float z = Mathf.Cos(i * ang + a) * r;
                list[i].transform.localPosition = new Vector3(x, 0, z);
            }
        }, moveAng, moveAng - AlignAng, time).OnComplete(()=>
        {
            SetRadar();
        });
        
    }
    //雷达图arr赋值
    public void SetRadar()
    {
        for (int i = 0; i < radar.arr.Length; i++)
        {
            radar.arr[i] = Random.Range(0.1f, radar.max);
            
        }
        radar.SetAllDirty();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PlayerMove : MonoBehaviour
{
    Camera cam;
    Vector3 pos;
    // Start is called before the first frame update
    void Start()
    {
        cam = Camera.main;
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void OnMouseDown()
    {
        float z = cam.WorldToScreenPoint(transform.position).z;
        pos = cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, z));
    }
    private void OnMouseDrag()
    {
        float z = cam.WorldToScreenPoint(transform.position).z;
        Vector3 pos0 = cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, z));
        float dis = pos0.x - pos.x;
        transform.parent.GetComponent<RotationChart>().Move(dis);
        pos = pos0;
    }
    private void OnMouseUp()
    {
        float z = cam.WorldToScreenPoint(transform.position).z;
        Vector3 pos0 = cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, z));
        float dis = pos0.x - pos.x;
        transform.parent.GetComponent<RotationChart>().Inertia(dis);
        pos = pos0;
    }
}

2d轮转图

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

public class RotationChart2D : MonoBehaviour,IDragHandler,IEndDragHandler
{
    public Image prefab;//预制体
    public float max;//缩放最大值
    public float min;//缩放最小值
    public float cut;//减速度
    public float spacing;//UI间距的单位是像素
    public int n;//个数
    public RadarMap radar;
    float c;//周长
    float r;//半径
    float ang;//弧度
    List<Image> list = new List<Image>();
    List<Transform> sortlist = new List<Transform>();
    float moveAng = 0;//拖动的弧度
    // Start is called before the first frame update
    void Start()
    {
        //周长=(宽+间距)*个数
        c = (prefab.rectTransform.rect.width + spacing) * n;
        //半径=周长/2π
        r = c / (2 * Mathf.PI);
        //弧度=周长/半径/个数
        ang = 2 * Mathf.PI / n;
        Move();
    }

    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<Text>().text = i.ToString();
                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;
            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++)
        {
            //改变img的顺序
            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(()=> 
        {
            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;
        //需要旋转的弧度=与中间偏差的弧度+间隔的弧度
        float AlignAng = Mathf.Asin(sortlist[n - 1].GetComponent<RectTransform>().anchoredPosition.x / r) + spAng;
        //通过需要旋转的弧度计算需要旋转的距离
        float Aligndis = AlignAng * r;
        //通过需要旋转的距离计算旋转的时间
        float time = Mathf.Abs(Aligndis) / cut;
        DOTween.To((a) =>
        {
            moveAng = a;
            Move();
        }, moveAng, moveAng - AlignAng, time).OnComplete(() =>
        {
            SetRadar();
        });

    }

    //雷达图arr赋值
    public void SetRadar()
    {
        for (int i = 0; i < radar.arr.Length; i++)
        {
            radar.arr[i] = Random.Range(radar.min, radar.max);

        }
        radar.SetAllDirty();
    }
}

雷达图

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 雷达图
/// </summary>

public class RadarMap : MaskableGraphic
{
    public Texture2D sprite;
    public Texture2D[] textures;
    public Color bj = Color.white;
    public float[] arr = new float[3];
    public float max;
    public float min;
    public override Texture mainTexture
    {
        get
        {
            if (sprite != null)
            {
                return sprite;
            }
            if (material != null && material.mainTexture != null)
            {
                return material.mainTexture;
            }
            return s_WhiteTexture;
        }
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        sprite = new Texture2D(0, 0);
        Rect[] rects= sprite.PackTextures(textures, 0);



        Rect rect = this.rectTransform.rect;
        float w = rect.width;
        float h = rect.height;
        vh.Clear();
        vh.AddVert(new Vector3(rect.x, rect.y, 0), bj, new Vector2(rects[0].x,rects[0].y));
        vh.AddVert(new Vector3(rect.x, rect.y + h, 0), bj, new Vector2(rects[0].x, rects[0].y+ rects[0].height));
        vh.AddVert(new Vector3(rect.x + w, rect.y, 0), bj, new Vector2(rects[0].x+ rects[0].width, rects[0].y));
        vh.AddVert(new Vector3(rect.x + w, rect.y + h, 0), bj, new Vector2(rects[0].x+ rects[0].width, rects[0].y+ rects[0].height));
        vh.AddTriangle(0,1,3);
        vh.AddTriangle(0,3,2);
        int n = arr.Length;
        float r = w < h ? w / 2 : h / 2;
        if (n >= 3)
        {
            vh.AddVert(Vector3.zero, color, new Vector2(rects[1].x+rects[1].width/2, rects[1].y + rects[1].height/2));
            float ang = 2 * Mathf.PI / n;
            float p = r / max;
            for (int i = 0; i < n; i++)
            {
                float x = Mathf.Sin(ang * i) * (arr[i] > max ? max : arr[i]) * p;
                float y = Mathf.Cos(ang * i) * (arr[i] > max ? max : arr[i]) * p;
                float uvx = (x + r) / (2 * r);
                float uvx0 = rects[1].x + rects[1].width * uvx;
                float uvy = (y + r) / (2 * r);
                float uvy0 = rects[1].y + rects[1].height * uvy;
                vh.AddVert(new Vector3(x, y, 0), color, new Vector2(uvx0, uvy0));
                if (i == 0)
                {
                    vh.AddTriangle(0+4, n+4, 1+4);
                }
                else
                {
                    vh.AddTriangle(0+4, i+4, i +1+4);
                }
            }
        }
       
    }
}

 

posted on 2023-02-25 09:46  a帝  阅读(31)  评论(0编辑  收藏  举报