unity 贝塞尔曲线实例化应用

项目中画曲线功能,Gizmos.DarwLine和Debug.DarwLine在打包exe后无法显示,Linerenderer手动填坐标麻烦。本文介绍用二次贝塞尔曲线公式计算生成曲线及所需点位,将公式带入Unity的LineRenderer中画曲线,还附上求导和正切方向计算公式。

项目中常常会用到画曲线的功能,不管是Gizmos.DarwLine还是Debug.DarwLine都满足不了打包之后在exe中显示。

虽然Linerenderer可以画,但是自己一点点的填写坐标非常麻烦。所以这里将用到贝塞尔曲线公式计算生成一条曲线以及生成一条曲线在Linerenderer中所需要多少个点位。

这里有篇博客将贝塞尔曲线的原理和推导公式都讲解的非常清楚,有兴趣可以了解下:https://blog.youkuaiyun.com/cfan927/article/details/104649623/

我这里将用二次贝塞尔曲线公式在LineRenderer中画一条曲线,下面是原理图:

定义:二次贝塞尔曲线的路径由给定点P0 、P1​、P2​的函数B(t)给出:
B ( t ) = ( 1 − t ) 2 P 0 + 2 t ( 1 − t ) P 1 + t 2 P 2 ,   t ∈ [ 0 , 1 ] 

我们在将该公式带入到unity中,将B理解为一个求导结果即Vector3向量,t为时间(即当前点移动到下一个点时间)t 取值0 - 1;

上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LineRender : MonoBehaviour
{
    private LineRenderer lineRenderer;
    public Vector3 p0;
    public Vector3 p1;
    public Vector3 p2;
    private Vector3 result;
    private List<Vector3> vectorList= new List<Vector3>();
    private float Nowtime = 0;
    private float timeLerp;
    private float maxTime = 1f;
    void Start()
    {
        lineRenderer = gameObject.GetComponent<LineRenderer>();
        
        p0 = new Vector3(0,0,0);
        p1 = new Vector3(5,5,5);
        p2 = new Vector3(10,0,10);
    }
    void FixedUpdate()
    {
        if (Nowtime > maxTime)
        {
            return;
        }

        CalculateVectorPoint();

        lineRenderer.positionCount = vectorList.ToArray().Length;
        if (lineRenderer.positionCount >= 2)
        {
            lineRenderer.SetPositions(vectorList.ToArray());
        }
    }
    void CalculateVectorPoint()
    {
        result = new Vector3();
        timeLerp = Mathf.Lerp(0, 1, Nowtime / maxTime);
        result.x = Mathf.Pow(1 - timeLerp, 2) * p0.x + 2 * timeLerp * Mathf.Pow(1 - timeLerp, 1) * p1.x + Mathf.Pow(timeLerp, 2) * p2.x;
        result.y = Mathf.Pow(1 - timeLerp, 2) * p0.y + 2 * timeLerp * Mathf.Pow(1 - timeLerp, 1) * p1.y + Mathf.Pow(timeLerp, 2) * p2.y;
        result.z = Mathf.Pow(1 - timeLerp, 2) * p0.z + 2 * timeLerp * Mathf.Pow(1 - timeLerp, 1) * p1.z + Mathf.Pow(timeLerp, 2) * p2.z;
        vectorList.Add(result);
        Nowtime = Nowtime + Time.deltaTime;
    }
}

 效果图如下:

 最后附上二次贝塞尔曲线求导公式和正切方向计算公式:

//二次贝塞尔曲线求导公式:(1 - t)^2 * P0 + 2t(1 - t)P1 + t^2 * P2,t=[0,1]
            transform.position = Mathf.Pow((1 - dt), 2) * StartPos + 2 * dt * (1 - dt) * HeightPos + Mathf.Pow(dt, 2) * TargetPos;
            //二次贝塞尔曲线正切方向求导公式: 2t(P2 + P0 - 2*P1) + 2(P1 - P0),t=[0,1]
            transform.up = 2 * dt * (TargetPos + StartPos - 2 * HeightPos) + 2 * (HeightPos - StartPos);

 

### 如何在 Unity 中实现循环曲线滚动效果 #### 设计思路 为了实现在Unity中的循环曲线滚动效果,可以借鉴圆形旋转滚动视图的设计理念[^3]。该方法涉及创建一系列沿着特定路径移动的对象,并通过编程手段让这些对象按照预设轨迹平滑运动。 #### 关键技术点 - **路径定义**:首先需要确定一条闭合的曲线作为物体移动的基础路线。 - **节点分布**:沿这条曲线上均匀布置多个节点用于放置待滚动的对象实例。 - **动态更新**:编写脚本来控制各个节点上的对象不断向前推进并形成连续不断的视觉流动感。 #### 实现步骤详解 ##### 一、准备阶段 1. 使用`Spline`或自定义算法来构建所需的曲线形状; 2. 在场景中添加一个空GameObject作为父级容器,用来承载所有的子物件; ##### 二、核心逻辑开发 下面是一个简单的C#代码片段展示如何基于给定的时间参数t,在0到1之间变化时获取对应于某条贝塞尔样条上任意一点的位置: ```csharp using UnityEngine; public class BezierCurve : MonoBehaviour { public Vector3[] points; // 控制点数组 private void Update() { float t = Time.time * speed % 1f; transform.position = CalculateBezierPoint(t); } /// <summary> /// 计算三次方程式的贝塞尔曲线上的某个位置. /// </summary> private Vector3 CalculateBezierPoint(float t) { int n = points.Length - 1; Vector3 result = new Vector3(); for (int i = 0; i <= n; ++i){ float blend = Binomial(n, i) * Mathf.Pow((1-t),n-i)*Mathf.Pow(t,i); result += points[i]*blend; } return result; } static float Binomial(int n,int k){ if(k==0 || n==k)return 1; else return Factorial(n)/(Factorial(k)*Factorial(n-k)); } static float Factorial(int value){ if(value<=1)return 1; else return value*Factorial(value-1); } } ``` 上述代码实现了基本的功能框架,即根据时间变量`t`的变化计算出当前时刻应该位于贝塞尔曲线上的哪个具体坐标处。 ##### 三、优化与完善 考虑到实际应用可能涉及到大量元素的同时渲染以及性能消耗等问题,建议采取如下措施加以改进: - 对象池机制:预先加载一定量的游戏资源存入内存缓存区,当有新的显示请求到来时直接从中取出而无需重新实例化; - 数据结构简化:尽可能减少不必要的属性存储,比如利用局部变换代替全局位移操作等技巧降低复杂度。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值