该代码实现了一个2D的可旋转的物品展示界面,用户可以通过拖动界面进行旋转,在界面上呈现出一圈圆形排列的物品。具体实现方法是通过计算圆的半径和物品数量以及设置物品之间的间距,计算每个物品在圆上的位置和大小,并实现随着距离的改变而缩放的效果。同时,当用户拖动结束后,界面将根据用户拖动的速度缓慢减速到停止,并将位于最右侧的物品移到最左侧。
该代码使用了DOTween插件实现物品旋转和减速动画效果,同时也使用了Unity的事件系统来响应用户的拖动事件,并使用了RectTransform组件实现2D界面中物体的排列和缩放效果。
这段代码可以用于游戏中的物品展示、商场中的商品展示等场景,具有良好的交互性和视觉效果。
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using UnityEngine.EventSystems;
public class RotaryFigure2D : MonoBehaviour,IDragHandler,IEndDragHandler
{
public GameObject prefab; //预制体对象
private float ang; //预制体之间的夹角
private float r; //旋转半径
private List<GameObject> list = new List<GameObject>(); //对象列表
private float num = 6; //预制体数量
private float p; //圆周长
private float spacing = 10; //两个预制体之间的间距
private float des; //旋转的目标位置
private List<Transform> trlist = new List<Transform>(); //预制体的Transform组件列表
private float scalinMax = 1; //预制体最大缩放值
private float scalinMin = 0.5f; //预制体最小缩放值
private float speed = 10; //拖动的速度
// Start is called before the first frame update
void Start()
{
ang = (2 * Mathf.PI) / num;
p = (prefab.GetComponent<RectTransform>().sizeDelta.x + spacing) * num;
r = p / (2 * Mathf.PI);
Move();
}
//旋转函数
public void Move()
{
float moveAng = (des / p) * (2 * Mathf.PI); //计算当前旋转的角度
for (int i = 0; i < num; i++)
{
float x = Mathf.Sin(ang * i + moveAng) * r;
float z = Mathf.Cos(ang * i + moveAng) * r;
//如果当前预制体对象数量小于i,就添加一个新的预制体对象
if (list.Count<=i)
{
list.Add(Instantiate(prefab,transform));
trlist.Add(list[i].transform);
}
list[i].transform.localPosition=Vector3.right * x ;
float scratio = 1 - (z + r) / (2 * r);
list[i].transform.localScale = Vector3.one * ((scalinMax - scalinMin) * scratio + scalinMin);
}
//根据预制体缩放大小,进行排序
trlist.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;
}
});
//重新设置预制体的SiblingIndex
for (int i = 0; i < trlist.Count; i++) {
trlist[i].SetSiblingIndex(i);
}
}
// Update is called once per frame
void Update()
{
}
//开始拖动时触发
public void OnDrag(PointerEventData eventData)
{
des -= eventData.delta.x;
Move();
}
//拖动结束时触发
public void OnEndDrag(PointerEventData eventData)
{
//计算拖动的时间
float time = Mathf.Abs(eventData.delta.x) / speed;
time = time > 2 ? 2 : time;
//进行平滑的拖动效果
DOTween.To((float a) => { des -= a; Move(); }, eventData.delta.x, 0, time).SetEase(Ease.InOutQuad).OnComplete(() => {
//找到最右侧预制体的位置,根据此位置进行位置的调整
float moveAng = Mathf.Asin(trlist[trlist.Count - 1].localPosition.x / r);
float movedes = moveAng / (2 * Mathf.PI) * p;
float moveTime = Mathf.Abs(movedes) / speed;
DOTween.To((float b) => { des = b; Move(); }, des, des + movedes, moveTime).OnComplete(() => {
print(1); //模拟调整完毕的回调函数
});
});
}
}