C# 在Unity中沿光线投射实例化预定义数量的对象

C# 在Unity中沿光线投射实例化预定义数量的对象,c#,unity3d,2d,raycasting,C#,Unity3d,2d,Raycasting,我有一个基于2个点的每一帧渲染的光线投射,这2个点在每一帧改变位置 我需要的是一个系统,它不需要一个方向,也不需要很多对象,而是取2个点,然后实例化或销毁尽可能多的对象,以将实例化的对象从一个方向移到另一个方向,减去点之间的空格。如果你想的话,你可以把它想象成一个基于光线投射的物体,除非没有重力 我的脚本: public int numOfPoints; // The number of points that are generated (This would need to chna

我有一个基于2个点的每一帧渲染的光线投射,这2个点在每一帧改变位置

我需要的是一个系统,它不需要一个方向,也不需要很多对象,而是取2个点,然后实例化或销毁尽可能多的对象,以将实例化的对象从一个方向移到另一个方向,减去
点之间的空格
。如果你想的话,你可以把它想象成一个基于光线投射的物体,除非没有重力

我的脚本:

    public int numOfPoints; // The number of points that are generated (This would need to chnage based one the distance in the end)
    public float spaceBetweenPoints; // The spacing between the generated points
    private GameObject[] predictionPoints; // The prefab to be gernerated
    private Vector2 firstPathStart; // The starting point for the raycast (Changes each frame)
    private Vector2 firstPathEnd; // The ending point for the raycast (Changes each frame)
    
    void start()
    {
         predictionPoints = new GameObject[numOfPoints];
         for (int i = 0; i < numOfPoints; i++)
         {
              predictionPoints[i] = Instantiate(predictionPointPrefab, firePoint.position, 
              Quaternion.identity);
         }
    }

    void Update
    {
         Debug.DrawLine(firstPathStart, firstPathEnd, UnityEngine.Color.black);
         DrawPredictionDisplay();
    }

    void DrawPredictionDisplay()
    {
         for (int i = 0; i < numOfPoints; i++)
        {
            predictionPoints[i].transform.position = predictionPointPosition(i * spaceBetweenPoints);
        }
    }

    Vector2 predictionPointPosition(float time)
    {
        Vector2 position = (Vector2)firstPathStart + direction.normalized * 10f * time;
        return position;
    }

注意事项:

    public int numOfPoints; // The number of points that are generated (This would need to chnage based one the distance in the end)
    public float spaceBetweenPoints; // The spacing between the generated points
    private GameObject[] predictionPoints; // The prefab to be gernerated
    private Vector2 firstPathStart; // The starting point for the raycast (Changes each frame)
    private Vector2 firstPathEnd; // The ending point for the raycast (Changes each frame)
    
    void start()
    {
         predictionPoints = new GameObject[numOfPoints];
         for (int i = 0; i < numOfPoints; i++)
         {
              predictionPoints[i] = Instantiate(predictionPointPrefab, firePoint.position, 
              Quaternion.identity);
         }
    }

    void Update
    {
         Debug.DrawLine(firstPathStart, firstPathEnd, UnityEngine.Color.black);
         DrawPredictionDisplay();
    }

    void DrawPredictionDisplay()
    {
         for (int i = 0; i < numOfPoints; i++)
        {
            predictionPoints[i].transform.position = predictionPointPosition(i * spaceBetweenPoints);
        }
    }

    Vector2 predictionPointPosition(float time)
    {
        Vector2 position = (Vector2)firstPathStart + direction.normalized * 10f * time;
        return position;
    }

  • direction
    是我在编辑器中设置的动量,我需要它来组合我当前的工作,但在基于点运行时不需要它

    • 我希望我正确地理解了你的意思

      首先,计算A到B的线,所以B减去A。 要获得所需对象的数量,请将“线幅值”除以对象的间距。还可以添加预测点对象的直径以避免重叠。 然后,为了得到每个对象的位置,写(几乎)相同的for循环

      这是我想到的,没有测试过,如果有用请告诉我

      public class CustomLineRenderer : MonoBehaviour
      {
          public float SpaceBetweenPoints;
          public GameObject PredictionPointPrefab;
          
          // remove transforms if you need to
          public Transform start;
          public Transform end;
      
          private List<GameObject> _predictionPoints;
          
          // these are your raycast start & end point, make them public or whatever
          private Vector2 _firstPathStart;
          private Vector2 _firstPathEnd;
      
          private void Awake()
          {
              _firstPathStart = start.position;
              _firstPathEnd = end.position;
              _predictionPoints = new List<GameObject>();
          }
      
          private void Update()
          {
              _firstPathStart = start.position;
              _firstPathEnd = end.position;
              
              // using any small value to clamp everything and avoid division by zero
              if (SpaceBetweenPoints < 0.001f) SpaceBetweenPoints = 0.001f;
      
              var line = _firstPathEnd - _firstPathStart;
              var objectsNumber = Mathf.FloorToInt(line.magnitude / SpaceBetweenPoints);
              var direction = line.normalized;
      
              // Update the collection so that the line isn't too short
              for (var i = _predictionPoints.Count; i <= objectsNumber; ++i)
                  _predictionPoints.Add(Instantiate(PredictionPointPrefab));
      
              for (var i = 0; i < objectsNumber; ++i)
              {
                  _predictionPoints[i].SetActive(true);
                  _predictionPoints[i].transform.position = _firstPathStart + direction * (SpaceBetweenPoints * i);
              }
      
              // You could destroy objects, but it's better to add them to the pool since you'll use them quite often
              for (var i = objectsNumber; i < _predictionPoints.Count; ++i)
                  _predictionPoints[i].SetActive(false);
          }
      }
      
      公共类CustomLineRenderer:MonoBehavior { 点之间的公共浮动空间; 公共游戏对象预测点预制; //如果需要,请删除变换 公共转型启动; 公共转换终端; 私有列表_预测点; //这些是您的raycast起点和终点,将其公开或其他任何内容 私有向量2_firstPathStart; 私有向量2_firstPathEnd; 私人空间 { _firstPathStart=start.position; _firstPathEnd=end.position; _predictionPoints=新列表(); } 私有void更新() { _firstPathStart=start.position; _firstPathEnd=end.position; //使用任何小值钳制所有内容并避免被零除 如果(SpaceBetweenPoints<0.001f)SpaceBetweenPoints=0.001f; 变量行=_firstPathEnd-_firstPathStart; var objectsNumber=Mathf.floorpoint(line.magnity/SpaceBetweenPoints); var方向=直线。标准化; //更新集合,使行不会太短
      对于(var i=\u predictionPoints.Count;i如果你问我,我会说,如果你知道一点数学技巧,这是很容易的。我不是说我数学很好,但一旦你得到它,下次就很容易完成。在这里,如果我试图解释一切,我将无法解释清楚。看看下面的代码,我已经对完整的代码,使您可以轻松理解

      基本上,我使用了一种称为
      Vector2.Lerp()
      线性插值的方法,这意味着该方法将根据第三个参数
      t
      的值返回
      0到1
      之间的值

      public class TestScript : MonoBehaviour
      {
          public Transform StartPoint;
          public Transform EndPoint;
          public float spaceBetweenPoints;
      
          [Space]
          public Vector2 startPosition;
          public Vector2 endPosition;
      
          [Space]
          public List<Vector3> points;
      
          private float distance;
      
          private void Update()
          {
              startPosition = StartPoint.position; //Setting Starting point and Ending point.
              endPosition = EndPoint.position;
          
              //Finding the distance between point
              distance = Vector2.Distance(startPosition, endPosition);
      
              //Generating the points
              GeneratePointsObjects();
      
              Debug.DrawLine(StartPoint.position, EndPoint.position, Color.black);
          }
      
          private void OnDrawGizmos()
          {
              //Drawing the Dummy Gizmo Sphere to see the points
              Gizmos.color = Color.black;
              foreach (Vector3 p in points)
              {
                  Gizmos.DrawSphere(p, spaceBetweenPoints / 2);
              }
          }
      
          private void OnValidate()
          {
              //Validating that the space between two objects is not 0 because that would be Raise an exception "Devide by Zero"
              if (spaceBetweenPoints <= 0)
              {
                  spaceBetweenPoints = 0.01f;
              }
          }
      
          private void GeneratePointsObjects()
          {
              //Vlearing the list so that we don't iterate over old points
              points.Clear();
      
              float numbersOfPoints = distance / spaceBetweenPoints; //Finding numbers of objects to be spawned by dividing "distance" by "spaceBetweenPoints"
              float increnment = 1 / numbersOfPoints; //finding the increment for Lerp this will always be between 0 to 1, because Lerp() takes value between 0 to 1;
      
              for (int i = 1; i < numbersOfPoints; i ++)
              {
                  Vector3 v = Vector2.Lerp(startPosition, endPosition, increnment * i); //Find next position using Vector2.Lerp()
                  points.Add(v);//Add the newlly found position in List so that we can spwan the Object at that position.
              }
          }
      }
      
      公共类测试脚本:MonoBehavior
      {
      公共转换起点;
      公共转换端点;
      点之间的公共浮动空间;
      [空格]
      公共矢量2起始位置;
      公共向量2末端位置;
      [空格]
      公共名单点;
      私人浮动距离;
      私有void更新()
      {
      startPosition=StartPoint.position;//设置起点和终点。
      endPosition=EndPoint.position;
      //求点与点之间的距离
      距离=矢量2.距离(起始位置、结束位置);
      //生成点
      生成点对象();
      DrawLine(StartPoint.position、EndPoint.position、Color.black);
      }
      private void OnDrawGizmos()
      {
      //绘制虚拟Gizmo球体以查看点
      Gizmos.color=color.black;
      foreach(矢量3 p点)
      {
      Gizmos.DrawSphere(p,点间距/2);
      }
      }
      私有void OnValidate()
      {
      //正在验证两个对象之间的空间不是0,因为这将引发异常“Device by Zero”
      
      如果(spaceBetweenPoints我认为你的想法是正确的,你的脚本看起来比较接近。但是,无论你做什么,距离似乎都是基于
      spaceBetweenPoints
      ,这意味着当你将
      spaceBetweenPoints
      设置为0.5f这样的小值时,你会得到一条与rayc方向相同的短线ast,但当它从光线投射开始时,它不是移除适当数量的点,而是将它们相对地紧密地放在一起,而不会到达光线投射的末端。如果使用更高的数字,如10,方向仍然正确,点分布在10f,但再次,不是移除适当数量的点,点会消失远超过光线投射的长度。但是如果你能修复你当前的代码,使其删除适当数量的点,而不是让它们消失,直到我们用完点为止。你的脚本可能会工作。同样,我希望我理解正确。在这里,我只显示或隐藏给定一组固定长度的点(你的游戏对象数组)。这样你就不会有太多的实例化和销毁操作,因为它占用了大量内存。如果你想动态创建更多的对象来填充这行内容,它非常非常类似:只需使用游戏对象列表。在运行for循环之前,如果集合太小,请更新它。看看我的代码片段,我更新了它。我对d很满意我想你知道我在大部分时间里都在尝试做什么,但我确实有一个问题,那就是你的更新代码依赖于变换,而我的光线投射的起点和终点使用矢量2。你的新代码还创建了大量的
      ArgumentOutOfRangeException:Index超出范围运行时出现范围
      错误。我使用了两个私有字段,它们是Vector2,这里的转换只是为了测试
      private void Update()
      {
          startPosition = StartPoint.position; //Setting Starting point and Ending point.
          endPosition = EndPoint.position;
      
          //Finding the distance between point
          distance = Vector2.Distance(startPosition, endPosition);
      
          //Generating the points
          GeneratePointsObjects();
      
          //Update: Generating points/dots on all to location;
          InstenciatePrefabsOnPositions();
      
          Debug.DrawLine(StartPoint.position, EndPoint.position, Color.black);
      }
      
      private void InstenciatePrefabsOnPositions()
      {
          //Remove all old prefabs/objects/points
          for (int i = 0; i < pointParent.childCount; i++)
          {
              Destroy(pointParent.GetChild(i).gameObject);
          }
      
          //Instantiate new Object on the positions calculated in GeneratePointsObjects()
          foreach (Vector3 v in points)
          {
              Transform t = Instantiate(pointPrefab);
              t.SetParent(pointParent);
              t.localScale = Vector3.one;
              t.position = v;
              t.gameObject.SetActive(true);
          }
      }