在大部分游戏中,都会有选角的时候使用轮转图,或者在有多个选项的时候使用轮转图。
今天就制作一个简单地3D轮转图。
首先创建一个空对象,一个预制体。
这里我选用的是Sphere当做预制体。
然后创建Coyclogram脚本挂在空对象上
我们要先整理自己的思路,预制体的数量,弧度,半径,等一系列东西
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cyclogram : MonoBehaviour
{
public GameObject prefab; //预制体
public int num; //数量
public float r; //半径
List<GameObject> list = new List<GameObject>();
List<Transform> sort = new List<Transform>();
float ang;
public float dec = 0.8f;
将这些定义好以后,先实例化出来我们的物体
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);
}
}
将prefab存放到集合中,之后遍历用到
然后写拖拽的方法
float allang = 0;
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);
}
}
写到这里之后,可以看到我们第一张图片上在预制体上获取了一个item脚本让里面的一个属性等于这个脚本。在item脚本里写拖拽方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CyclogramItem : MonoBehaviour
{
public Cyclogram cyclogram;
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);
}
}
写到这里之后就有拖拽的效果了,但是光有拖拽的效果还不行,游戏中拖拽结束之后会有一个复位的效果,接下来我们要完成复位,判断物体的localPosition的z 轴和圆心的距离然后利用DOTween移动 (这个是在Cyclogram里封装的方法)
public void Inertin(float dis)
{
float time = Mathf.Abs(dis / dec);
DOTween.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);
DOTween.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);
});
然后再去Item里调用
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.Inertin(dis);
}
这样我们就可以做出来一个简易版的3D轮转图了
最后不要忘了设置空对象上公开的属性