1.3d轮转图就是像一个圆形,然后拖动旋转
代码如下:
把物体数量和轮转图的半径声明为一个变量,这里我们用小球做示范,创建一个预制体
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotationChart : MonoBehaviour
{
public GameObject prefeb;
public int num;//数量
public float r;//半径
public float dec=5;
float ang;//弧度
public List<GameObject> list=new List<GameObject>();
public List<Transform> sort=new List<Transform>();
// Start is called before the first frame update
void Start()
{
ang = 2 * Mathf.PI / num;
for (int i = 0; i < num; i++)
{
//计算顶点
float x=Mathf.Sin(ang*i)*r;
float z=Mathf.Cos(ang*i)*r;
GameObject sphere = Instantiate(prefeb);
sphere.transform.parent = transform;
sphere.transform.localPosition = new Vector3(x, 0, z);
sphere.GetComponent<RotationItem>().rotationChart = this;
list.Add(sphere);
sort.Add(sphere.transform);
}
}
把每个物体的位置赋值
接下来把每个物体添加下一下脚本,是关于3d拖拽的坐标转换
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotationItem : MonoBehaviour
{
public RotationChart rotationChart;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnMouseDrag()
{
Vector3 pos=Camera.main.WorldToScreenPoint(transform.position);
Vector3 next = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, pos.z));
float dis=next.x-transform.position.x;
rotationChart.OnDrag(dis);
}
private void OnMouseUp()
{
Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
Vector3 next = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, pos.z));
float dis = next.x - transform.position.x;
rotationChart.Inertia(dis);
}
}
在第一个脚本里继续写拖拽的方法,拖动后把拖动后的位置赋值给物体
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(ang * i+allang) * r;
float z = Mathf.Cos(ang * i + allang) * r;
list[i].transform.localPosition = new Vector3(x, 0, z);
}
}
接下来是一个运用dotween的缓动效果(惯性)并且区中对齐效果
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(ang * i + allang) * r;
float z = Mathf.Cos(ang * i + allang) * r;
list[i].transform.localPosition = new Vector3(x, 0, z);
}
}, allang, allang + aligning, aligningtime);
});
}
最后手写了一个简单的dotween,运用到缓动效果
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.WSA;
public class DT : MonoBehaviour
{
public Action<float> action;
public float begin;
public float end;
public float time;
public Action complete;
float nowtime;
public static DT To(Action<float> action,float begin,float end,float time)
{
GameObject dotween = new GameObject("DT");
DT dt= dotween.AddComponent<DT>();
dt.action = action;
dt.begin = begin;
dt.end = end;
dt.time = time;
dt.nowtime = Time.time;
return dt;
}
// Update is called once per frame
void Update()
{
if (Time.time - nowtime < time)
{
float t = Time.time - nowtime;
float p = t / time;
float a = begin * (1 - p) + end * p;
action(a);
}
else
{
action(end);
if(complete!=null)
{
complete();
}
Destroy(gameObject);
}
}
public void OnComplete(Action complete)
{
this.complete = complete;
}
}
效果如下