2D轮转图与3D轮转图的原理基本一样,只是2D少了距离的轴,所以近大远小的效果使用物体的缩放来进行实现:
先进行数据的初始化赋值:
public Image prefeb;
public int num;
float d;
float r;
float angle;
float angel_all;
List<GameObject> objs = new List<GameObject>();
List<Transform> pos = new List<Transform>();
private void Start()
{
d = num * (prefeb.rectTransform.sizeDelta.x + 30);
r = d / 2 / Mathf.PI;
angle = 2 * Mathf.PI / num;
Move();
}
计算出生成物体所在圆的半径以及夹角后生成物体,生成物体物体之间的遮挡关系会出现问题,所以要对物体重新排序显示:
public void Move()
{
for (int i = 0; i < num; i++)
{
if (objs.Count <= i)
{
objs.Add(Instantiate(prefeb.gameObject, transform));
pos.Add(objs[i].transform);
}
float x = Mathf.Sin(i * angle + angel_all) * r;
float z = Mathf.Cos(i * angle + angel_all) * r;
float p = (z + r) / (r + r);
float scale = (1 - p) + p / 2;
objs[i].transform.localPosition = new Vector3(x, 0, 0);
objs[i].transform.localScale = Vector3.one * scale;
}
pos.Sort((a, b) => (int)(a.localPosition.z - b.localPosition.z));
for (int i = 0; i < pos.Count; i++)
{
pos[i].SetSiblingIndex(i);
}
}
2D的拖拽使用UGUI事件系统实现更为简单,引入UnityEngine.EventSystems命名空间,然后继承IDragHandler, IEndDragHandler接口:
public void OnDrag(PointerEventData eventData)
{
angel_all -= eventData.delta.x / r;
Move();
}
public void OnEndDrag(PointerEventData eventData)
{
float dis = eventData.delta.x;
DOTween.To(() => dis, t =>
{
angel_all -= t / r;
Move();
}, 0, 2).OnComplete(() =>
{
float angle_move = Mathf.Asin(pos[num - 1].localPosition.x / r);
DOTween.To(() => angel_all, t =>
{
angel_all = t;
Move();
}, angel_all + angle_move, 1);
});
}
在拖拽时不断读取鼠标横轴的偏移量,根据偏移量计算后调用Move方法刷新界面的物体信息,这样一个简单的2D轮转图就做好了:
接下来制作抽奖的效果:给每个物体添加一个文本组件,然后按生成顺序给文本组件赋值:
objs[i].GetComponentInChildren<Text>().text = i.ToString()
然后做一个抽奖按钮生成随机数字进行抽奖:
根据生成的随机数计算后移动到对应位置:
public void Lottery()
{
int n = Random.Range(0, num);
Debug.Log(n);
int now = objs.IndexOf(pos[num - 1].gameObject);
float angel_move = 0;
angel_move = (now - n) * angle;
DOTween.To(() => angel_all, t =>
{
angel_all = t;
Move();
}, angel_all + angel_move, 2);
}
最终效果: