Unity中,给定起点终点,据此生成一条曲线
2023-07-04 本文已影响0人
全新的饭
思路
基于贝塞尔曲线,再给定一个控制点,用于控制曲线轨迹。
示意:如图红色球表示起点、蓝色球表示终点,黄色球表示控制点。
生成曲线.gif
关键代码
// 根据起点、终点、控制点、采样点数,获取贝塞尔曲线(点集)
private Vector3[] GetBeizerPosList(Vector3 begin, Vector3 ctrl, Vector3 end, int cnt)
{
cnt--;
Vector3[] path = new Vector3[cnt + 1];
path[0] = begin;
for (int i = 1; i <= cnt; i++)
{
float t = i / (float)cnt;
Vector3 curPos = CalculateCubicBezierPoint(t, begin, ctrl, end);
path[i] = curPos;
}
return path;
}
// 根据t,算得贝塞尔曲线上对应的点
// p0~2分别是起点、控制点、终点
private Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 p = uu * p0;
p += 2 * u * t * p1;
p += tt * p2;
return p;
}
上述示意图用到的代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fan_CreateCurve : MonoBehaviour
{
[SerializeField]
private Transform _beginTrans;
private Vector3 BeginPos { get { return _beginTrans.position; } }
[SerializeField]
private Transform _endTrans;
private Vector3 EndPos { get { return _endTrans.position; } }
[SerializeField]
private Transform _ctrlTrans;
private Vector3 CtrlPos { get { return _ctrlTrans.position; } }
[SerializeField]
private int _cnt = 10;
[SerializeField]
private Transform _curveRoot;
private Transform[] _curve;
private void Start()
{
Init();
}
private void Update()
{
MyUpdate();
}
private void OnDestroy()
{
MyDestroy();
}
private void Init()
{
}
private void MyUpdate()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (_curve != null)
{
for (int i = _curve.Length - 1; i >= 0; i--)
{
Destroy(_curve[i].gameObject);
}
_curve = null;
}
_curve = new Transform[_cnt];
var _curvePoints = GetBeizerPosList(BeginPos, CtrlPos, EndPos, _cnt);
for (int i = 0; i < _cnt; i++)
{
_curve[i] = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
_curve[i].transform.position = _curvePoints[i];
_curve[i].transform.SetParent(_curveRoot);
}
}
}
private void MyDestroy()
{
}
// 根据起点、终点、控制点、采样点数,获取贝塞尔曲线(点集)
private Vector3[] GetBeizerPosList(Vector3 begin, Vector3 ctrl, Vector3 end, int cnt)
{
cnt--;
Vector3[] path = new Vector3[cnt + 1];
path[0] = begin;
for (int i = 1; i <= cnt; i++)
{
float t = i / (float)cnt;
Vector3 curPos = CalculateCubicBezierPoint(t, begin, ctrl, end);
path[i] = curPos;
}
return path;
}
// 根据t,算得贝塞尔曲线上对应的点
// p0~2分别是起点、控制点、终点
private Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 p = uu * p0;
p += 2 * u * t * p1;
p += tt * p2;
return p;
}
}