贝塞尔曲线demo

 参考软管地址

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

public class Bei_sai_er : MonoBehaviour
{
    public Transform startTrans;
    public Transform endTrans;

    [Header("高度")]
    public float height;
    [Header("顶点移动偏移")]
    public float forward_distance=0.5f;
    [Header("路径点数量")]
    public int resolution;
    [Header("目标点偏移")]
    public Vector3 offset;


    [Header("line_render")]
    public LineRenderer _lineRender;
    [Header("投掷的物品")]
    public Transform grenade;

    //路径点arr
    private Vector3[] _path;
    private Vector3 startPoint;
    private Vector3 endPoint;
    private Vector3 bezierControlPoint;
  
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {

        if (Input.GetMouseButton(0))
        {
            Line_show();
        }
        if (Input.GetMouseButtonUp(0))
        {
            _lineRender.gameObject.SetActive(false);
            if (_path!=null)
            {
                grenade.DOPath(_path, 0.8f).SetLookAt(0).SetEase(Ease.Linear);
            }
           
        }
    }
    /// <param name="t">0到1的值,0获取曲线的起点,1获得曲线的终点</param>
    /// <param name="start">曲线的起始位置</param>
    /// <param name="center">决定曲线形状的控制点</param>
    /// <param name="end">曲线的终点</param>
    public static Vector3 GetBezierPoint(float t, Vector3 start, Vector3 center, Vector3 end)
    {
        return (1 - t) * (1 - t) * start + 2 * t * (1 - t) * center + t * t * end;
    }

    private void Line_show()
    {
        startPoint = startTrans.position;

        Ray ray_demo = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if(Physics.Raycast(ray_demo,out hit, Mathf.Infinity))
        {
            if (hit.transform .name== "Plane")
            {

                _lineRender.startColor=Color.yellow;
                _lineRender.endColor = Color.green;
            }
            else
            {

                _lineRender.startColor = Color.red;
                _lineRender.endColor = Color.red;
            }

            endPoint = hit.point + offset;
            _lineRender.gameObject.SetActive(true);
            bezierControlPoint = (startPoint + endPoint) * forward_distance + (Vector3.up * height);

            _path = new Vector3[resolution];//resolution为int类型,表示要取得路径点数量,值越大,取得的路径点越多,曲线最后越平滑
            for (int i = 0; i < resolution; i++)
            {
                var t = (i + 1) / (float)resolution;//归化到0~1范围
                _path[i] = GetBezierPoint(t, startPoint, bezierControlPoint, endPoint);//使用贝塞尔曲线的公式取得t时的路径点
            }

            _lineRender.positionCount = _path.Length;
            _lineRender.SetPositions(_path);
        }
        else
        {
           
             Vector3 mousePosInWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
          
            

             endPoint = mousePosInWorld;

            _path = new Vector3[resolution];//resolution为int类型,表示要取得路径点数量,值越大,取得的路径点越多,曲线最后越平滑
            for (int i = 0; i < resolution; i++)
            {
                var t = (i + 1) / (float)resolution;//归化到0~1范围
                _path[i] = GetBezierPoint(t, startPoint, bezierControlPoint, endPoint);//使用贝塞尔曲线的公式取得t时的路径点
            }

            _lineRender.positionCount = _path.Length;
            _lineRender.SetPositions(_path);
        }


      


    }
   
}

以下为模拟电线连接线

 

 

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

public class Bezier : MonoBehaviour
{

    public static Vector3 GetPoint(Vector3 p0, Vector3 p1, Vector3 p2, float t)
    {
        t = Mathf.Clamp01(t);
        float oneMinusT = 1f - t;
        return
            oneMinusT * oneMinusT * p0 +
            2f * oneMinusT * t * p1 +
            t * t * p2;
    }

}

 

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

public struct BezierLineSegment
{
    public Vector3 fromPoint;
    public Vector3 toPoint;
    public Vector3 controlPoint;
    public Quaternion fromDir;
    public Quaternion toDir;

    public void CalculateDir()
    {
        fromDir = Quaternion.FromToRotation(Vector3.forward, controlPoint - fromPoint);
        toDir = Quaternion.FromToRotation(Vector3.forward, toPoint - controlPoint);
    }

    public bool IsStraight()
    {
        return fromDir == toDir;
    }
    
}

[ExecuteInEditMode]
public class BezierPipe : MonoBehaviour
{

    public float cornerScale = 1f;
    [Range(1, 100)]
    public int cornerStep = 10;
    [Range(2, 100)]
    public int circleStep = 10;

    public float r = 0.1f;

    public Transform point1;
    public Vector3 point1Dir = Vector3.up;
    public Transform point2;
    public Vector3 point2Dir = Vector3.up;

    public bool update = false;

    public Mesh mesh;
    List<Vector3> verts = new List<Vector3>();
    List<int> triangles = new List<int>();
    private MeshCollider mc;
    [Header("控制弯曲下垂度")]
    public Vector3 center_control;
    // Use this for initialization
    void Start()
    {
        mesh = new Mesh();
        mesh.name = "Pipe";
        MeshFilter mf = GetComponent<MeshFilter>();
        if (mf != null)
        {
            mf.sharedMesh = mesh;
        }
        mc = GetComponent<MeshCollider>();
        if (mc != null)
        {
            mc.sharedMesh = mesh;
        }
        BuildMesh();
    }

    // Update is called once per frame
    void Update()
    {
        if (update)
        {
            BuildMesh();
        }
    }
    void GetCirclePoint(Vector3 pos, Quaternion dir, bool draw)
    {
        for (int a = 0; a <= circleStep; a++)
        {
            float p = 2 * Mathf.PI * a / circleStep;
            Vector3 cp = new Vector3(r * Mathf.Cos(p), r * Mathf.Sin(p), 0);
            cp = dir * cp + pos;
            //if(draw)
            //    Gizmos.DrawSphere(cp, 0.0005f);
            cp = transform.worldToLocalMatrix.MultiplyPoint(cp);
            //cp += transform.position;
            verts.Add(cp);
        }
    }

    void SetTriangles()
    {
        triangles.Clear();
        for (int i = 0; i < verts.Count - circleStep - 2; i++)
        {
            triangles.Add(i);
            triangles.Add(i + 1);
            triangles.Add(i + circleStep + 1);
            triangles.Add(i + circleStep + 1);
            triangles.Add(i + 1);
            triangles.Add(i + circleStep + 2);
        }
        mesh.triangles = triangles.ToArray();
    }

    public void BuildMesh()
    {
        if (point1 != null && point2 != null)
        {
            verts.Clear();
            float scale = cornerScale;
            float length = (point1.position - point2.position).magnitude / 4;
            if (scale > length)
            {
                scale = length;
            }
            BezierLineSegment[] segments = new BezierLineSegment[3];
            segments[0].fromPoint = point1.position;
            point1Dir.Normalize();
            segments[0].controlPoint = point1.position + point1.rotation * point1Dir * scale;

            segments[2].toPoint = point2.position;
            point2Dir.Normalize();
            segments[2].controlPoint = point2.position + point2.rotation * point2Dir * scale;

            segments[1].controlPoint = (segments[0].controlPoint + segments[2].controlPoint) / 2+ center_control;

            segments[0].toPoint = segments[1].fromPoint = segments[0].controlPoint + (segments[1].controlPoint - segments[0].controlPoint).normalized * scale;
            segments[1].toPoint = segments[2].fromPoint = segments[2].controlPoint + (segments[1].controlPoint - segments[2].controlPoint).normalized * scale;

            transform.position = segments[1].controlPoint;
            segments[1].CalculateDir();
            transform.rotation = segments[1].fromDir;
            //            Debug.Log (transform.eulerAngles);

            foreach (var segment in segments)
            {
                segment.CalculateDir();
                if (segment.IsStraight())
                {
                    GetCirclePoint(segment.fromPoint, segment.fromDir, true);
                    GetCirclePoint(segment.controlPoint, segment.fromDir, false);
                    GetCirclePoint(segment.toPoint, segment.toDir, true);
                    //Gizmos.DrawLine(segment.fromPoint, segment.controlPoint);
                    //Gizmos.DrawLine(segment.controlPoint, segment.toPoint);
                }
                else
                {
                    GetCirclePoint(segment.fromPoint, segment.fromDir, true);
                    Vector3 p1 = segment.fromPoint;
                    for (int s = 1; s < cornerStep; s++)
                    {
                        float t = (float)s / cornerStep;
                        Vector3 p2 = Bezier.GetPoint(segment.fromPoint, segment.controlPoint, segment.toPoint, t);
                        //Quaternion dir = Quaternion.FromToRotation(Vector3.forward, p2 - p1);
                        Quaternion dir = Quaternion.Lerp(segment.fromDir, segment.toDir, t);
                        GetCirclePoint(p2, dir, false);
                        //Gizmos.DrawLine(p1, p2);
                        p1 = p2;
                    }
                    GetCirclePoint(segment.toPoint, segment.toDir, true);
                    //Gizmos.DrawLine(p1,segment.toPoint);
                }
            }
            mesh.Clear();
            mesh.vertices = verts.ToArray();
            SetTriangles();
            mesh.RecalculateNormals();

            if (mc != null)
            {
                mc.sharedMesh = mesh;
            }
        }
    }
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值