旋转前:
旋转后:
3D旋转效果代码部分:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 3D轮转图
/// </summary>
public class CreateLun : MonoBehaviour
{
public GameObject prefab;//预制体
float spacing = 10; //间距
int num = 5; //个数
float c; //周长
float r; //半径
float ang; //每个角的弧度
List<GameObject> cubes = new List<GameObject>(); //物品集合
List<Transform> sortlist = new List<Transform>(); //位置集合
float distance = 0; //拖动的距离
void Start()
{
//计算周长
c = (1 + spacing) * num;
//计算半径
r = c / (Mathf.PI * 2);
//计算每个角的弧度
ang = 2 * Mathf.PI / num;
for (int i = 0; i < num; i++)
{
cubes.Add(Instantiate(prefab, transform));
float x = Mathf.Sin(i * ang) * r;
float z = Mathf.Cos(i * ang) * r;
cubes[i].transform.localPosition = new Vector3(x, 0, z);
cubes[i].AddComponent<PMove>();
sortlist.Add(cubes[i].transform);
}
}
//差值移动
public void Move(float dis)
{
distance -= dis;
float moveang = distance / r;
int count = cubes.Count;
for (int i = 0; i < count; i++)
{
float x = Mathf.Sin(i * ang + moveang) * r;
float z = Mathf.Cos(i * ang + moveang) * r;
cubes[i].transform.localPosition = new Vector3(x, 0, z);
}
//给存起来的位置进行排序
sortlist.Sort((a, b) =>
{
if (a.localPosition.z > b.localPosition.z)
return 1;
else if(a.localPosition.z == b.localPosition.z)
return 0;
else
return -1;
});
int counts = sortlist.Count;
for (int i = 0; i < counts; i++)
sortlist[i].SetSiblingIndex(i);
}
//拖拽时鼠标抬起是的惯性计算
public void Insrtin(float dis)
{
float timer = dis / speed;
timer = timer > 2 ? timer : 2;
DOTween.To((float index) =>
{
distance -= index;
Move(index);
}, dis, 0, timer).SetEase(Ease.InOutQuad).OnComplete(() =>
{
float moveang = Mathf.Sin(sortlist[sortlist.Count - 1].localPosition.x / r);
float movedis = moveang / (Mathf.PI * 2) * c;
DOTween.To((float indexs) =>
{
distance = indexs;
Move(indexs);
}, distance, distance + movedis, 2f);
Agtne(sortlist[sortlist.Count - 1].GetComponent<CreateCube>().id);
});
}
public void Agtne(int index)
{
int a = sortlist[sortlist.Count - 1].GetComponent<CreateCube>().id;
int b = a - index;
int s = num - Mathf.Abs(b);
int d = s > Mathf.Abs(b) ? b : (b > 0 ? -s : s);
float moveang = Mathf.Sin(sortlist[sortlist.Count - 1].localPosition.x / r) + (d * ang);
float movedis = moveang / (Mathf.PI * 2) * c;
DOTween.To((float indexss) =>
{
distance = indexss;
Move(0);
},distance,distance + movedis,2f).OnComplete(()=>
{
});
}
}
拖转3D物体时的代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PMove : MonoBehaviour
{
Vector3 pos;
//拖拽时的差值
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));
float dis = (pos0 - pos).x;
transform.parent.GetComponent<CreateLun>().Move(dis);
pos = pos0;
}
//鼠标按下是的位置记录
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 OnMouseUp()
{
float z = Camera.main.WorldToScreenPoint(transform.position).z;
Vector3 pos0 = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, z));
float dis = (pos0 - pos).x;
transform.parent.GetComponent<CreateLun>().Insrtin(dis);
pos = pos0;
}
}
而想要3D物体移动时带有惯性效果,则可分为一下写法:
一、手写DoTween效果:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 3D轮转图
/// </summary>
public class CreateLun : MonoBehaviour
{
public float dec = 0.8f; //减速度
public void Insrtin(float dis)
{
float time = Mathf.Abs(dis / dec);
DT.To((a) =>
{
Move(a);
}, dis, 0, time);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class DT : MonoBehaviour
{
public Action<float> action;
public float begin;
public float end;
public float time;
float nowtime;
public static DT To(Action<float> action, float begin, float end, float time)
{
GameObject dt = new GameObject("DT");
DT doween = dt.AddComponent<DT>();
doween.action = action;
doween.begin = begin;
doween.end = end;
doween.time = time;
doween.nowtime = Time.time;
return doween;
}
// Update is called once per frame
void Update()
{
if (Time.time - nowtime < time)
{
float t = Time.time - nowtime;
float p = t / nowtime;
float a = begin * (1 - p) + end * p;
action(a);
}
else
{
action(end);
Destroy(gameObject);
}
}
}
二、使用DoTween插件实现惯性效果
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using DG.Tweening;
using Newtonsoft.Json;
using System;
public class CreateLunBo : MonoBehaviour,IDragHandler,IEndDragHandler
{
public GameObject prefab; //预制体
public int num = 9; //数量
//最大值 最小值 间距 拖动的距离
float max = 1f, min = 0.5f, scaping = 1.5f, distance = 0;
//半径 周长 每个角的弧度 速度
float r, c, ang, speed = 10;
List<GameObject> list = new List<GameObject>();
List<Transform> sortlist = new List<Transform>();
private void Move()
{
float moveAng = (distance / c) * Mathf.PI * 2;
for (int i = 0; i < num; i++)
{
float x = Mathf.Sin(moveAng + i * ang) * r;
float z = Mathf.Cos(moveAng + i * ang) * r;
if (list.Count <= i)
{
list.Add(Instantiate(prefab, transform));
list[i].transform.name = i.ToString();
list[i].AddComponent<Call>();
list[i].GetComponent<Call>().id = i;
sortlist.Add(list[i].transform);
}
list[i].transform.localPosition = Vector3.right * x;
float scale = 1 - (r + z) / (2 * r);
list[i].transform.localScale = Vector3.one * ((max - min) * scale + min);
if (list[i].transform.localScale.x < 0.75f)
{
list[i].SetActive(false);
}
else
{
list[i].SetActive(true);
}
}
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;
});
int count = sortlist.Count;
for (int i = 0; i < count; i++)
sortlist[i].SetSiblingIndex(i);
}
public void OnDrag(PointerEventData eventData)
{
distance -= eventData.delta.x;
Move();
}
public void OnEndDrag(PointerEventData eventData)
{
float timer = Mathf.Abs(eventData.delta.x) / speed;
timer = timer > 2 ? timer : 2;
DOTween.To((float index) =>
{
distance -= index;
Move();
},eventData.delta.x, 0, timer).SetEase(Ease.InOutQuad).OnComplete(() =>
{
float moveang = Mathf.Sin(sortlist[sortlist.Count - 1].localPosition.x / r);
float movedis = moveang / (Mathf.PI * 2) * c;
DOTween.To((float index1) =>
{
distance = index1;
Move();
}, distance, distance + movedis, 2f);
Agtne(sortlist[sortlist.Count - 1].GetComponent<Call>().id);
});
}
public void Agtne(int index)
{
int a = sortlist[sortlist.Count - 1].GetComponent<Call>().id;
int b = a - index;
int s = num - Mathf.Abs(b);
int d = s > Mathf.Abs(b) ? b : (b > 0 ? -s : s);
float moveang = Mathf.Sin(sortlist[sortlist.Count - 1].localPosition.x / r) + (d * ang);
float movedis = moveang / (Mathf.PI * 2) * c;
DOTween.To((float indexs) =>
{
distance = indexs;
Move();
}, distance, distance + movedis, 2f).OnComplete(() =>
{
});
}
}