一、3D轮转图的制作
一、生成预制体、移动、惯性
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class Cyclogram : MonoBehaviour
{
public GameObject prefab;//生成的预制体
public int num;//个数
public float r;//半径
public float dec = 0.8f;//减速度
List<GameObject> list = new List<GameObject>();
List<Transform> sort = new List<Transform>();
float ang;//每个角的弧度
float allang = 0;
// 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(i * ang) * r;
float z = Mathf.Cos(i * ang) * r;
GameObject sphere = Instantiate(prefab);
sphere.transform.parent = transform;
sphere.transform.localPosition = new Vector3(x, 0, z);
sphere.GetComponent<CyclogramItem>().cyclogram = this;
list.Add(sphere);
sort.Add(sphere.transform);
}
}
public void OnDrag(float dis)
{
//计算移动的弧度 = 距离 / 半径
float moveang = dis / r;
allang -= moveang;
for (int i = 0; i < list.Count; i++)
{
float x = Mathf.Sin(i * ang + allang) * r;
float z = Mathf.Cos(i * ang + allang) * r;
list[i].transform.localPosition = new Vector3(x, 0, z);
}
}
//惯性
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(i * ang + allang) * r;
float z = Mathf.Cos(i * ang + allang) * r;
list[i].transform.localPosition = new Vector3(x, 0, z);
}
}, allang, allang + aligning, aligningtime);
});
}
// Update is called once per frame
void Update()
{
}
}
二、预制体身上的OnMouseDrag和OnMouseUp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CyclogramItem : MonoBehaviour
{
public Cyclogram cyclogram;
// 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;
cyclogram.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;
cyclogram.Inertia(dis);
}
}
三、手写DOTween
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DT : MonoBehaviour
{
public Action<float> action;
public float begin;
public float end;
public float time;
float nowtime;
public Action complete;
public static DT To(Action<float> action, float begin, float end, float time)
{
GameObject dt = new GameObject("DT");
DT dowteen = dt.AddComponent<DT>();
dowteen.action = action;
dowteen.begin = begin;
dowteen.end = end;
dowteen.time = time;
dowteen.nowtime = Time.time;
return dowteen;
}
// 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);
}
if(time >= 5)
{
time = 3;
}
}
public void OnComplete(Action complete)
{
this.complete = complete;
}
}
二、曲面轮转图
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CreareCamber : MonoBehaviour
{
//曲面Mesh
private float n = 15;
private float l;
public float r;
void Start()
{
l = 150 * n;
r = l / (2 * Mathf.PI);
float ang = 2 * Mathf.PI / n;
float sunang = 2 * Mathf.PI / (n * 10);
VertexHelper vh = new VertexHelper();
for (int i = -5; i <=5; i++)
{
float x = Mathf.Sin(i * sunang) * r - Mathf.Sin(0) * r;
float z = Mathf.Cos(i * sunang) * r - Mathf.Cos(0) * r;
float y = 113;
float y0 = -113;
float uvx = (float)(i + 5) / 10;
vh.AddVert(new Vector3(x, y, z), Color.white, new Vector2(uvx, 1));
vh.AddVert(new Vector3(x, y0, z), Color.white, new Vector2(uvx, 0));
if (i<5)
{
int j = i + 5;
vh.AddTriangle(j * 2 + 1, j * 2, (j + 1) * 2);
vh.AddTriangle(j * 2 + 1, (j + 1) * 2, (j + 1) * 2 + 1);
}
}
Mesh mesh = new Mesh();
vh.FillMesh(mesh);
GetComponent<MeshFilter>().mesh = mesh;
GetComponent<MeshCollider>().sharedMesh = mesh;
}
// Update is called once per frame
void Update()
{
}
}