利用DOTween插件做一个贝塞尔曲线实例(一普通版)

文章介绍了一种在Unity游戏中用于调试飞行效果的工具,该工具利用DOTween进行位移处理,并基于贝塞尔函数计算路径点,实现更高效的轨迹调整。通过封装函数和使用LineRenderer组件,创建可见的飞行轨迹线,便于观察和优化。作者计划进一步优化工具,包括调整轨迹速度,添加动画曲线功能,并实现飞行的暂停与恢复控制。
摘要由CSDN通过智能技术生成

        平时在工作中,会经常遇到一些飞行效果的调试,每次和策划调轨迹的时候都会消耗程序大量的时间,所以我就写了一个简单的工具,主要是利用DOTween做位移,贝塞尔函数算出路径点的信息,在携程里面去跑,话不多说,上代码

首先我们需要写一个N阶贝塞尔的脚本

using System.Collections.Generic;
using UnityEngine;

public class BeizerTool
{


    /// <summary>
    /// n次贝塞尔调用
    /// </summary>
    /// <param name="vertex"></param>
    /// <param name="vertexCount"></param>
    /// <returns></returns>
    public static Vector3[] GetBeizerList_n(Vector3[] vertex, int vertexCount)
    {
        List<Vector3> pointList = new List<Vector3>();
        pointList.Clear();
        for (float ratio = 0; ratio <= 1; ratio += 1.0f / vertexCount)
        {
            pointList.Add(Bezier_n(vertex, ratio));
        }
        //  pointList.Add(vertex[vertex.Length - 1]);


        return pointList.ToArray();
    }

    private static Vector3 Bezier_n(Vector3[] vecs, float t)
    {
        Vector3[] temp = new Vector3[vecs.Length];
        for (int i = 0; i < temp.Length; i++)
        {
            temp[i] = vecs[i];
        }
        //顶点集合有多长,曲线的每一个点就需要计算多少次。


        int n = temp.Length - 1;
        for (int i = 0; i < n; i++)
        {
            //依次计算各两个相邻的顶点的插值,并保存,每次计算都会进行降阶。剩余多少阶计算多少次。直到得到最后一条线性曲线。


            for (int j = 0; j < n - i; j++)
            {
                temp[j] = Vector3.Lerp(temp[j], temp[j + 1], t);
            }
        }
        //返回当前比例下曲线的点
        return temp[0];
    }

}

然后呢,我们需要封装一下他的调用

public void MoveToBeizer(Transform _transform, Vector3[] bzizerVec, float time, Action _Compelte,bool Isword)
    {
        StartCoroutine(BeizerTween(_transform, bzizerVec, time, _Compelte, Isword));
    }

    IEnumerator BeizerTween(Transform _transform, Vector3[] bzizerVec, float time, Action _Compelte, bool Isword)
    {
        Vector3[] CurrArray = BeizerTool.GetBeizerList_n(bzizerVec, (int)(time * 50));
        int index = 0;
        float counter = 0;
        while (counter < time)
        {
            counter += Time.fixedDeltaTime;
            if (Isword is true)
            {
                _transform.DOMove(CurrArray[index], 0.01f);
            }
            else
                _transform.DOLocalMove(CurrArray[index], 0.01f);
           
            index += 1;
            if (index> CurrArray.Length-1)
            {
                index = CurrArray.Length - 1;
            }
            yield return new WaitForFixedUpdate();
        }
        if (_Compelte != null)
            _Compelte.Invoke();
    }

最后了 我们主要用unity的组件lineRender去绘制一条可见的轨迹线

using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class BzLine : MonoBehaviour
{
    [Header("移动的物体")]
    public Transform target;  // 目标物体
    [Header("飞行时间控制")]
    public float line_time = 5f;
    [Header("重新开始按钮")]
    public Button _button;
    private LineRenderer lineRenderer;
    [Header("起始点,n个拐点,终点")]
    public List<Vector3> points = new();
    private List<Vector3> points1;
    [Header("是否启用世界坐标")]
    public bool pos_type = true;


    public Tween tween;
    void Start()
    {
        _button.onClick.AddListener(tryAgain);
        lineRenderer = gameObject.AddComponent<LineRenderer>();
        points1 = new List<Vector3>();
        //MoveToBeizer(target, points.ToArray(), line_time, null, true);
    }

    void tryAgain()
    {
        MoveToBeizer(target, points.ToArray(), line_time, null, pos_type);
    }

    public void MoveToBeizer(Transform _transform, Vector3[] bzizerVec, float time, Action _Compelte, bool Isword)
    {
        StartCoroutine(BeizerTween(_transform, bzizerVec, time, _Compelte, Isword));
    }

    IEnumerator BeizerTween(Transform _transform, Vector3[] bzizerVec, float time, Action _Compelte, bool Isword)
    {
        target.transform.position = points[0];
        lineRenderer.positionCount = 0;
        Destroy(lineRenderer);
        points1.Clear();
        yield return new WaitForSeconds(0.1f);
        lineRenderer = gameObject.AddComponent<LineRenderer>();
        lineRenderer.startWidth = 1f;
        lineRenderer.endWidth = 1f;
        Vector3[] CurrArray = BeizerTool.GetBeizerList_n(bzizerVec, (int)(time * 50));
        int index = 0;
        float counter = 0;
        while (counter < time)
        {
            counter += Time.fixedDeltaTime;
            if (Isword is true)
            {
                _transform.DOMove(CurrArray[index], 0.01f);
            }
            else
                _transform.DOLocalMove(CurrArray[index], 0.01f);

            index += 1;
            if (index > CurrArray.Length - 1)
            {
                index = CurrArray.Length - 1;
            }
            yield return new WaitForFixedUpdate();
        }
        if (_Compelte != null)
            _Compelte.Invoke();
        //_transform.gameObject.AddComponent<CanvasGroup>().DOFade(0, 1).OnComplete(delegate() {
        //    Destroy(_transform.gameObject);
        //});
    }

    void Update()
    {
        // 获取目标物体的位置,并添加到路径点列表

        points1.Add(target.position);
        // 更新LineRenderer的点
        if (lineRenderer)
        {
            lineRenderer.positionCount = points1.Count;
            lineRenderer.SetPositions(points1.ToArray());
        }
    }
}

这样就基本完成了一个简单的工具

下一期,我会优化这个工具,优化飞行的轨迹速度,添加动画曲线, 并且会封装一个Timer 可以控制飞行的暂停以及恢复,有时间再写吧

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值