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); } } } } }