1.动态生成对象实现平面圆上,弧边上规律生成
围绕圆的弧边动态生成对象
public GameObject prefab; //对象
public int num; //生成对象数量
public float r; //半径
float ang;
void Start()
{
ang = 2 * Mathf.PI / num;
//生成球
for (int i = 0; i < num; i++)
{
float x = Mathf.Sin(i * ang) * r; //位置x
float z = Mathf.Cos(i * ang) * r; //位置z
GameObject sphere = Instantiate(prefab); //生成对象
sphere.transform.parent = transform; //设置父对象
sphere.transform.localPosition = new Vector3(x, 0, z); //赋值位置
}
}
脚本挂载到空对象上 设置上面属性
运行后生成
2.实现鼠标拖动进行旋转 轮转效果
方法OnDrag用于接受拖动距离 对距离进行操作计数实现物体同步鼠标滑动移动
public GameObject prefab;
public int num;
public float r;
// Start is called before the first frame update
float ang;
List<GameObject> list = new List<GameObject>();
List<Transform> sort = new List<Transform>();
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);
}
}
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);
}
}
为预制体对象添加脚本 调用 OnDrag方法 , cyclogram是空物体脚本的实例
对物体坐标变成屏幕坐标,取z轴位置 同步与鼠标的位置一样
求出距离 调用 OnDrag 实现鼠标滑动物体,物体实现轮转效果
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);
}
3.实现物体加上惯性,拖动结束后,物体平滑缓慢停止 停止后可以实现对齐
下面提供完整代码,附上完整注释:
DowTeen
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>(); // 在游戏对象上添加DT组件
dowteen.action = action; // 设置动作回调函数
dowteen.begin = begin; // 设置动画开始的值
dowteen.end = end; // 设置动画结束的值
dowteen.time = time; // 设置动画的总时间
dowteen.nowtime = Time.time; // 记录动画开始的时间
return dowteen;
}
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; // 设置完成回调函数
}
}
CyclogramItem 轮转图对象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; // 计算物体在x轴上的位移
cyclogram.OnDrag(dis); // 将位移传递给cyclogram实例的OnDrag方法
}
// 当鼠标抬起时触发的方法
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; // 计算物体在x轴上的位移
cyclogram.Inertia(dis); // 将位移传递给cyclogram实例的Inertia方法
}
}
Cyclogram轮转图空对象代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cyclogram : MonoBehaviour
{
public GameObject prefab; // 预制体
public int num; // 圆数量
public float r; // 半径
public float dec = 0.8f; // 减速系数
float ang; // 每个圆之间的夹角
List<GameObject> list = new List<GameObject>(); // 圆的列表
List<Transform> sort = new List<Transform>(); // 排序列表
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; // 获取圆上的CyclogramItem组件,并设置cyclogram属性为当前脚本的引用
list.Add(sphere); // 添加到圆的列表中
sort.Add(sphere.transform); // 添加到排序列表中
}
}
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);
}
}
public void Inertia(float dis)
{
float time = Mathf.Abs(dis / dec);
DT.To((a) =>
{
OnDrag(a);
}, dis, 0, time).OnComplete(() =>
{
sort.Sort((a, b) =>
{
// 根据位置z坐标进行排序
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);
});
}
void Update()
{
}
}