我正在尝试创建一些类似于蛇的运动,但是我无法实现将一个身体部位笔直移动到另一个部位的算法,依此类推。
我想拥有一些自动移动的蛇,它由单独的方块(球体)组成。这条蛇应该沿着一条路径移动。我使用贝塞尔曲线样条生成路径,并且已经实现了一条未来的蛇形部分。头部的点是通过下一个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);
}
//....
}
就目前而言,如果我停止头部运动,那么所有零件都不会保持距离并继续移动到头部位置。上述算法的另一个问题是零件不会完全沿着头部路径移动。他们可以在转弯时“偷工减料”。 主要思想是仅对头部(第一身体部位)进行用户/人工智能控制,随后的每个部位都应正确重复头部路径并保持其邻居之间的距离。
答案 0 :(得分:0)
对于像蛇一样的运动,如果将球体视为单独的对象,则可能会出现许多奇怪的行为。虽然我可以想象有可能使其工作,但我认为这不是最佳方法。
想到的第一个解决方案是创建一个列表,在该列表上将在每帧上添加蛇头位置到索引0。 列表将增长,所有其他段将等待轮到,因此延迟x帧,并且在每个更新段y上的位置为list [x * y]
如果列表的Count()大于number_of_segments * lag,则删除RemoveAt(Count()-1)
这可以优化,因为更改列表有些昂贵(环形缓冲区会更适合,但队列也可以工作。对于初学者来说,我发现列表更容易遵循,您以后可以随时进行优化)。如果您的帧率变化很大,但总体来说应该非常稳定,这可能会有些尴尬(例如-不会出现不可预测的运动,我们只会反复使用相同的值)
第二种方法: 您提到使用贝塞尔曲线样条生成路径。贝塞尔曲线由浮点t参数化,因此您有类似
SplineAt(t).
如果您使用bezier_path_length和distance_between_segments,则段n的位置应为
SplineAt(t-n*distance_between_segments/bezier_path_length)