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;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读