C# 在Unity中沿光线投射实例化预定义数量的对象
我有一个基于2个点的每一帧渲染的光线投射,这2个点在每一帧改变位置 我需要的是一个系统,它不需要一个方向,也不需要很多对象,而是取2个点,然后实例化或销毁尽可能多的对象,以将实例化的对象从一个方向移到另一个方向,减去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
点之间的空格
。如果你想的话,你可以把它想象成一个基于光线投射的物体,除非没有重力
我的脚本:
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);
}
}