Unity中绘制抛物线

xiaoxiao2021-02-28  14

效果如下:   之所以加个2,是因为我以前写过一个抛物线的文章,之前的文章请看这: Unity绘制抛物线代码 上一篇文章只是简单地绘制了一个抛物线,但是无法随意移动或者旋转,最近因为做个项目可能会用到这个抛物线,所以我做了一些修改,现在抛物线可以跟随着起始点移动、旋转,还加入了碰撞盒检测的功能。 [C#]  纯文本查看  复制代码 ?   001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 using UnityEngine; using System.Collections; using System.Collections.Generic;   public class ParabolaRay : MonoBehaviour {      /*      抛物线公式:y=a*x*x+b*x+c,由于z轴方向为正方向,所以:y=a*z*z+b*z+c,我们把抛出点设为原点(0,0),所以抛物线为y=a*z*z+b*z。      */      public float a; //控制抛物线的开口和大小      private float k; //k为抛物线上抛出点的切线 y=kx+d 的斜率,我们把抛出点设为原点,所以:y = kx,k = 2ax +b      private float b; // 我们把抛出点设为坐标原点,所以由k = 2ax + b,b = k;      public LineRenderer line; //抛物线的LineRenderer组件      public int density; //抛物线的精度      public float space = 5; //每个节点间的间隔                         // y = a*space*space+b*space        public GameObject sphere;      List<GameObject> points = new List<GameObject>();      Vector3 prevPoint;      void Start()      {          for ( int i = 0; i < density; i++)          {              points.Add(Instantiate(sphere));          }          line.SetVertexCount(density+1);          prevPoint = transform.position;      }        // Update is called once per frame      void Update()      {          Vector3 f = transform.forward;          f.y = 0;          k = transform.forward.y/f.magnitude; //算出切线斜率(注意物体的旋转角度,当forward为垂直方向时,也就是f.magnitude的值为0的时候,应该为一条直线,这里没有考虑这个情况)          b = k;            bool cast = false ;          for ( int i = 0; i < density; i++)          {              Vector3 p = GetPosition(i * space);              points[i].transform.position = p;              cast = Cast(p);              if (cast)              {                  break ;              }          }          if (!cast)          {            }      }      /// <summary>      /// 根据z确定点坐标      /// </summary>      /// <param name="z"></param>      /// <returns></returns>      Vector3 GetPosition( float z)      {          float y = a * z * z + b * z;          Vector3 f = transform.forward;          f.y = 0;          f = f.normalized;            Vector3 pos = transform.position + f * z; //水平方向坐标          pos.y = transform.position.y + y; //加上垂直方向坐标          return pos;      }            /// <summary>      /// 进行抛物线检测      /// </summary>      /// <param name="currentPoint"></param>      /// <returns></returns>      bool Cast(Vector3 currentPoint)      {          Vector3 d = currentPoint - prevPoint;          RaycastHit hit;          if (Physics.Raycast(prevPoint, d.normalized, out hit, d.magnitude))          {              SetLine(hit.point);              prevPoint = transform.position;              return true ;          }          else          {              prevPoint = currentPoint;              return false ;          }      }        /// <summary>      /// 设置抛物线上每个点      /// </summary>      /// <param name="endPos"></param>      void SetLine(Vector3 endPos)      {          Vector3 s = transform.position;          endPos.y = 0;          s.y = 0;            float j = Vector3.Distance(s, endPos) / density;            for ( int i = 0; i < density; i++)          {              line.SetPosition(i, GetPosition(i * j));          }          line.SetPosition(density, endPos);          sphere.transform.position = endPos;      } } 在上面的代码中,我们把起始点作为坐标原点,把起始点的正方向作为抛物线的切线,然后我们只需要设置a值就能求出抛物线的方程了。 关于抛物线的斜率,三维空间和二维空间的斜率求法还是有区别的,如下图:    我们应该把向量的 垂直方向的长度/水平方向的长度 作为切线的斜率,但是这里要考虑到 向量与Y轴平行的情况 ,我的脚本里还没有加入这种情况的判断。 另外一点就是抛物线检测碰撞盒,我们可以把抛物线划分为若干段线段,每个线段进行一次检测,当检测到碰撞盒的时候,我们可以停止检测。 最后如果大佬觉得有什么地方不对的话,欢迎指正!
转载请注明原文地址: https://www.6miu.com/read-1650249.html

最新回复(0)