代码如下:(对比视频基本相同)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class beisaiercontroller : MonoBehaviour
{
public bool xianshi=true;//是否显示小球
public float ballsdistant = 0.3f;//小球素材球心距
public int sem;//多少段贝塞尔曲线
public GameObject ballprefab;
public List<GameObject> Controlpointlist = new List<GameObject>();
//在测试窗口进行绘制,随着鼠标移动进行刷新,一帧一次
public List<Vector3> balllist = new List<Vector3>();//最终的小球队列
private void Awake()
{
//将生成的所有素材小球位置点放到一个名为map的空物体中
foreach(var item in balllist)
{
GameObject ball= Instantiate(ballprefab, GameObject.Find("map").transform);
ball.transform.position = item;//将对应位置放到球中
}
}
private void OnDrawGizmos()
{
/*
* for(i=0;i<transform.childCount;i++)
* {
* tramsform.GetChild(i);
* }
* 与下方foreach效果等同
* */
Controlpointlist.Clear();//当删除小球时讲其清理出队伍
foreach (Transform item in transform)
{
Controlpointlist.Add(item.gameObject);//把所有的初始小球放到队列里
}
List<Vector3> pointpostlist = Controlpointlist.Select(ppostlist => ppostlist.transform.position).ToList();//获取小球坐标
var points = GetDrawingPoints(pointpostlist, sem);//接收所有点
//利用小球和球心距开始摆放小球素材
Vector3 startball = points[0];
//将起点放到最终小球队列里
balllist.Clear();
balllist.Add(startball);
for(int i=0;i<points.Count;i++)
{
if(Vector3.Distance(startball,points[i])>=ballsdistant)
{
startball = points[i];
balllist.Add(startball);
}
}
//遍历每一个初始小球如果不需要显示就不显示
foreach(var item in Controlpointlist)
{
item.GetComponent<MeshRenderer>().enabled = xianshi;
}
if (xianshi == false) return;
Gizmos.color = Color.red;
foreach(var item in balllist)//原本是points
{
Gizmos.DrawSphere(item, 0.16f);//坐标,运算小球直径
}
//绘制辅助线判断小球顺序
Gizmos.color = Color.blue;
for (int i= 0;i< pointpostlist.Count;i++)
{
Gizmos.DrawLine(pointpostlist[i], pointpostlist[i + 1]);
}
}
//读取四个点位
public List<Vector3> GetDrawingPoints(List<Vector3> controlpoints ,int fenliangsize)//fenliangsize是1的份数(分母)
{
List<Vector3> points = new List<Vector3>();//运算得出的小点为后续显示小弹珠打基础(从中截取合适的间隔来显示例如100个小点取5个显示)
for (int i = 0; i < controlpoints.Count-3; i+=3)
{
var p0 = controlpoints[i];
var p1 = controlpoints[i + 1];
var p2 = controlpoints[i + 2];
var p3 = controlpoints[i + 3];
for(int j=0;j<=fenliangsize;j++)
{
var t = j / (float)fenliangsize;
points.Add(cbersarerpoint(t, p0, p1, p2, p3));
}
}
return points;
}
//绘制贝塞尔曲线
public Vector3 cbersarerpoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
//t是参数,范围为0到1,包括0到1
var x = 1 - t;
//四个节点的贝塞尔曲线函数 p0*x^3+3*p1*t*x^2+3*p2*t^2*x+p3*t^3
return p0 * x * x * x + 3 * p1 * t * x * x + 3 * p2 * t * t * x + p3 * t * t * t;
}
}
unity版本号2018.4.30f1