定义
轮转图是游戏中较为常见的功能,在我们制作一些场景选关或者是做一些选择类似的UI时,我们会觉得想制作一种3D效果的选择方式,3D轮转图往往就是最恰当的一种
原理
利用父物体生成子物体选项,子物体利用x轴上的间距和 最中心靠前的物体最大显示(缩放最大),两侧物体逐渐变小(缩放逐渐变小)的原理制造视觉差,从而形成3D效果,之后利用DragHandler事件制作拖动旋转即可
第一步
创建一个空物体,将接下来的代码挂载在它的身上
第二步
创建预制体,以方便之后的实例化
第三步
对应代码如下
首先是生成多少个预制体和绘制位置信息和旋转轴半径
然后给预制体身上挂载一下脚本
第四步
接下来我们来实现一下拖动结束后可根据惯性,继续转动一小段距离
这里就需要用到dotween
我们来自己写一个dotween
代码如下:
第五步
写出一下对应函数在鼠标抬起的时候调用
调用:(写在挂载在预制体身上的脚本上)
第六步
Dotween脚本里添加一下方法
对空物体身上挂载的脚本进行完善
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CreateLun : MonoBehaviour
{
public GameObject prefab;
public int num;
public float r;
public float dec = 0.8f;//减速度
float ang;
// Start is called before the first frame update
List<GameObject> list = new List<GameObject>();
List<Transform> sort = new List<Transform>();
void Start()
{
ang = 2 * Mathf.PI / num;
for (int i = 0; i < num; i++)
{
float x = Mathf.Sin(i * ang) * r;
float z = Mathf.Cos(i * ang) * r;
GameObject sphere = Instantiate(prefab);
sphere.transform.parent = transform;
sphere.transform.localPosition = new Vector3(x, 0, z);
sphere.GetComponent<LunItem>().lun = this;
list.Add(sphere);
sort.Add(sphere.transform);
}
}
float allang = 0;
public void OnDrag(float dis)
{
float moveang = dis / r;
allang -= moveang;
for (int i = 0; i < list.Count; i++)
{
float x = Mathf.Sin(i * ang+allang) * r;
float z = Mathf.Cos(i * ang+allang) * r;
list[i].transform.localPosition = new Vector3(x, 0, z);
}
}
public void Inertia(float dis)
{
float time =Mathf.Abs(dis/dec);
DT.To((a) =>
{
OnDrag(a);
}, dis, 0, time).OnComplete(() => {
sort.Sort((a, b) =>
{
if (a.position.z < b.position.z)
{
return -1;
}
else if (a.position.z == b.position.z)
{
return 0;
}
else
{
return 1;
}
}
);
float aligning = Mathf.Asin(sort[0].localPosition.x / r);
float aligningtime = Mathf.Abs(aligning * r / dec);
DT.To((a) =>{
allang = a;
for (int i = 0; i < list.Count; i++)
{
float x = Mathf.Sin(i * ang + allang) * r;
float z = Mathf.Cos(i * ang + allang) * r;
list[i].transform.localPosition = new Vector3(x, 0, z);
}
},allang,allang+aligning, aligningtime);
});
}
// Update is called once per frame
void Update()
{
}
}