首先,根据轮转图个数和间距分别计算周长、半径、每个物体之间的弧度,根据三角函数计算每个物体的具体坐标位置,将生成的物体存入集合。
拖拽物体旋转,获取鼠标拖拽的距离和拖拽物体的位置坐标,计算拖拽的的距离,代码如下
private void OnMouseDown()
{
float z = Camera.main.WorldToScreenPoint(transform.position).z;
pos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, z));
}
private void OnMouseDrag()
{
float z = Camera.main.WorldToScreenPoint(transform.position).z;
Vector3 pos0 = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, z));
transform.parent.GetComponent<Rotate3D>().Move(pos0.x - pos.x);
pos = pos0;
}
调用物体移动的方法传入移动距离参数,根据距离计算移动的弧度重新设置每个物体的坐标位置
代码如下
public void Move(float dis)
{
distance += dis;
float moveAng = distance / r;
for (int i = 0; i < n; 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);
}
}
让物体具有旋转的惯性,首先获得抬起鼠标时的距离,根据减速速度计算得出减速所需要的时间
使用DoTween实现惯性效果
惯性结束再让物体对齐根据物体距离零点坐标的距离z轴来判断当前转到的是哪个物体
调用sortlist集合中的Sort方法排序,找出距离零点坐标的最小值sortlist[0]
根据sortlist[0]的位置来计算需要对齐的角度和移动的距离,并根据减速度计算出所需时间,
使用DoTween来实现对齐效果,代码如下
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 1;
}
else
{
return 0;
}
});
float AlignAng = Mathf.Atan(sortlist[0].localPosition.x / sortlist[0].localPosition.z);
float Aligndis = AlignAng * r;
float time = Mathf.Abs(Aligndis) / 1;
DT.To((a) =>
{
Move(a - distance);
}, distance, distance - Aligndis, time);
}
手写DoTween代码如下
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DT : MonoBehaviour
{
float nowTime, startTime, start, end, time;
Action<float> action;
Action complete;
// Start is called before the first frame update
public static DT To(Action<float> action,float start,float end,float time)
{
GameObject obj = new GameObject("DT");
DT dt = obj.AddComponent<DT>();
dt.action = action;
dt.start = start;
dt.time = time;
dt.end = end;
return dt;
}
void Start()
{
startTime = Time.time;
}
// Update is called once per frame
void Update()
{
if (nowTime<time)
{
nowTime = Time.time - startTime;
float p = nowTime / time;
float now = (end - start) * p + start;
action(now);
if (nowTime > time)
{
nowTime = time;
if (complete!=null)
{
complete();
}
Destroy(gameObject);
}
}
}
public void OnComplete(Action t)
{
this.complete = t;
}
}