首页 > 解决方案 > Unity中很少有物体一个接一个地直线移动

问题描述

我正在尝试创建一些类似蛇的运动,但我无法实现算法来将一个身体部位直接移动到另一个身体部位,依此类推。

我想要一些自动移动的蛇,它由单独的块(球体)组成。这条蛇应该沿着一些路径移动。我用贝塞尔样条生成路径,并且已经实现了一条未来蛇的部分。头部点是通过下一个 api 从样条获得的:

class BezierSpline
{
  Vector3 GetPoint(float progress) // 0 to 1
}

而且比我有 SnakeMovement 脚本

public class SnakeMovement : MonoBehaviour
{
  public BezierSpline Path;
  public List<Transform> Parts;
  public float minDistance = 0.25f;
  public float speed = 1;

//.....
void Update()
{
  Vector3 position = Path.GetPoint(progress);
  Parts.First().localPosition = position;
  Parts.First().LookAt(position + Path.GetDirection(progress));

  for (int i = 1; i < Parts.Count; i++)
  {
    Transform curBody = Parts[i];
    Transform prevBody = Parts[i - 1];
    float dist = Vector3.Distance(prevBody.position, curBody.position);

    Vector3 newP = prevBody.position;
    newP.y = Parts[0].position.y;
    float t = Time.deltaTime * dist / minDistance * curspeed;

    curBody.position = Vector3.Slerp(curBody.position, newP, t);
    curBody.rotation = Quaternion.Slerp(curBody.rotation, prevBody.rotation, t);
  }
  //....
}

现在,如果我停止头部移动,所有部件都不会保持距离并继续移动到头部位置。上述算法的另一个问题是零件不完全遵循头部路径。他们可以在转弯时“切入”弯道。主要思想是仅对头部(第一个身体部分)进行用户/ai控制,并且每个后续部分都应该准确地重复头部路径并保持其邻居之间的距离。

标签: algorithmunity3d

解决方案


对于类似蛇的运动,如果将球体视为单独的对象,则可能会出现许多奇怪的行为。虽然我可以想象它有可能让它工作,但我认为这不是最好的方法。

想到的第一个解决方案是创建一个列表,您将在每个帧上将蛇头的位置添加到索引 0 上。列表会增长,所有其他段将等待轮到它们,因此滞后 x 帧,并且在每个更新段上,y 将具有 list[x*y] 的位置

如果列表的 Count() 大于 number_of_segments*lag,则 RemoveAt(Count()-1)

这可以进行优化,因为更改列表的成本有点高(环形缓冲区更适合,但队列也可以工作。对于初学者来说,我发现列表更容易遵循,你可以随时优化)。如果你的帧率变化很大,这可能会有点尴尬,但通常应该非常稳定(如 - 没有不可预测的运动,我们只会一遍又一遍地重复使用相同的值)

第二种方法:您提到使用贝塞尔样条曲线生成路径。贝塞尔曲线由 float t 参数化,所以你有类似的东西

SplineAt(t).

如果您采用 bezier_path_length 和 distance_between_segments,则段 n 的位置应为

SplineAt(t-n*distance_between_segments/bezier_path_length)

推荐阅读