下面流程生成的是Cube预制体,生成不同模型,需要在代码里做细小的改动。
创建一个空物体,挂载轮转图3D脚本
为预制体挂载脚本
代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using DG.Tweening;
using UnityEngine.UIElements;
public class Cyclogram3D : MonoBehaviour
{
//预制体
public GameObject m_Prefab;
//预制体数量
public int m_Num;
//每两个预制体间的弧度
float m_Rad;
//剩余移动弧度
float m_MoveRad;
//预制体围成圆的半径
public float m_Radius;
//存储生成的预制体
List<GameObject> m_List = new List<GameObject>();
//用于排序
List<Transform> m_Trans = new List<Transform>();
internal void OnDragPrefab(float v)
{
m_MoveRad -= v / m_Radius;
OnMove();
}
/// <summary>
/// 惯性
/// </summary>
/// <param name="v">剩余横向偏移量</param>
internal void OnInertia(float v)
{
DOTween.To((a) =>
{
OnDragPrefab(a);
}, v, 0, 2).OnComplete(() =>
{
m_Trans.Sort((a, b) =>
{
return (int)(a.position.z - b.position.z);
});
OnAlign(m_List.IndexOf(m_Trans[0].gameObject));
});
}
/// <summary>
/// 对齐
/// </summary>
/// <param name="v">最前面的游戏对象在原m_List集合中的索引</param>
public void OnAlign(int v)
{
#region 指定查找,最短路径轮转
m_Trans.Sort((a, b) =>
{
return (int)(a.position.z - b.position.z);
});
int index = m_List.IndexOf(m_Trans[0].gameObject);
int zheng = index - v;
int fan = m_Num - Mathf.Abs(zheng);
fan = zheng < 0 ? fan : -fan;
int offset = Mathf.Abs(zheng) < Mathf.Abs(fan) ? zheng : fan;
float offsetAngle = offset * m_Rad;
#endregion
//只有指定查找,才加offsetAngle;不是指定查找,不用加
float totalRad = Mathf.Asin(m_Trans[0].position.x / m_Radius) + offsetAngle;
DOTween.To((a) =>
{
m_MoveRad = a;
OnMove();
}, m_MoveRad, m_MoveRad + totalRad, 2);
}
void Start()
{
m_Rad = 2 * Mathf.PI / m_Num;
OnMove();
}
private void OnMove()
{
for (int i = 0; i < m_Num; i++)
{
float x = Mathf.Sin(i * m_Rad + m_MoveRad) * m_Radius;
float z = Mathf.Cos(i * m_Rad + m_MoveRad) * m_Radius;
if (m_List.Count <= i)
{
GameObject go = Instantiate(m_Prefab, transform);
go.name = i.ToString();
m_List.Add(go);
m_Trans.Add(go.transform);
}
m_List[i].transform.position = new Vector3(x, 0, z);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cyclogram3D_Item : MonoBehaviour
{
private void OnMouseDrag()
{
Vector3 pos=Camera.main.WorldToScreenPoint(transform.position);
Vector3 mouse=Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y,pos.z));
transform.parent.GetComponent<Cyclogram3D>().OnDragPrefab(mouse.x - transform.position.x);
}
private void OnMouseUp()
{
Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
Vector3 mouse = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, pos.z));
transform.parent.GetComponent<Cyclogram3D>().OnInertia(mouse.x - transform.position.x);
}
}