我正在 Unity 中创建一个 3D 足球游戏,玩家可以在屏幕上绘制一条路径,而足球应该在 3D 空间中遵循这条路径。该路径应该考虑深度、高度和 X 轴。玩家应该能够在有限的空间内绘制路径,这就是为什么我使用一个看不见的盒子碰撞器来供玩家绘制。 但现在我没有得到所需的行为,即用户应该能够绘制考虑深度的路径,因此球可以沿着通往目标的路径,现在玩家可以在屏幕上绘制,但它是仅考虑 x 和 y 值。
我使用 LineRenderer 绘制路径,然后使用协程沿路径移动球。我实现了一个系统,用户绘制一条路径,然后在释放鼠标按钮或触摸时,球被设置到路径的起始位置并使用 Vector3.Lerp 沿路径移动。
private void Update()
{
// Left mouse button or touch.
if (Input.GetMouseButton(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// Raycast to the drawArea to draw the path.
if (Physics.Raycast(ray, out hit) && hit.collider == drawArea)
{
if (points.Count == 0 || (points.Count > 0 && Vector3.Distance(points[points.Count - 1], hit.point) > 0.1f))
{
points.Add(hit.point);
lineRenderer.positionCount = points.Count;
lineRenderer.SetPositions(points.ToArray());
}
}
}
if (Input.GetMouseButtonUp(0))
{
ball.position = points[0];
StartCoroutine(MoveBallAlongPath());
points.Clear();
lineRenderer.positionCount = 0;
}
}
private IEnumerator MoveBallAlongPath()
{
// The resolution of the path.
int resolution = 100;
for (int i = 0; i < points.Count - 1; i++)
{
Vector3 pointA = points[i];
Vector3 pointB = points[i + 1];
Vector3 controlPoint = (pointA + pointB) / 2;
for (int j = 0; j < resolution; j++)
{
float t = j / (float)resolution;
Vector3 pointOnLine = CalculateBezierPoint(t, pointA, controlPoint, pointB);
ball.position = pointOnLine;
yield return new WaitForEndOfFrame();
}
}
}
private Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 p = uu * p0;
p += 2 * u * t * p1;
p += tt * p2;
return p;
}
如果有帮助的话,我可以为此提供一个更简单的解决方案。将隐形盒子碰撞器仅覆盖整个球门柱正面。将有两次触摸/单击操作。第一次点击/触摸将设置球在地面上的位置。就像投射在场地/地面上的光线一样,将球与地面对齐,然后用鼠标/触摸移动球来设置球的位置,然后在完成后释放单击/触摸。下一次单击/触摸应该仅在球门柱上,以便将光线投射到不可见的盒子碰撞器上,以设置瞄准射击的位置。释放后,您可以将球直接射向连接两点的球门柱,也可以添加第三次和第四次单击操作,这可能会设置连接线的凹度/曲率。您可以显示两个小工具,一个将决定凹度,另一个将决定曲线的旋转,就像 3D 建模软件可能具有的那样。但如果你直接将球射向球门柱,就可以保持简单。