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

### 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();

//获取数据

}
public void Move()
{
for (int i = 0; i < n; i++)
{
//判断集合中有就不创建，没有再创建
if(list.Count<=i)
{

}

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.transform.position = new Vector3(0.45f, -2, 0);
player.transform.eulerAngles = new Vector3(0, 180, 0);

});
}
}