Unity3D BezierCurve-跟随AI的Spline Walker?

问题描述 投票:1回答:1

我一直在努力开发一款具有能力(但还算不错)的赛车AI的游戏,但我有很多要满足的限制。以下是条件:

1。)AI逻辑和播放器控件共享相同的汽车控制器来驾驶和转弯,依此类推。根据车辆试图转弯的距离以及转弯的距离,AI车辆只需传递一个固定的(-1到1)值。油门接合。 AI和玩家都共享布尔值以刹车,并使用SHIFT键漂移漂移]

2。)AI需要做出明智,明智的决策,让玩家做出正确的转弯,何时滑行等操作。>

我最初使用普通的航路点增量系统,以使AI继续根据航路点在轨道上重叠。有了合适的车轮摩擦曲线值(我很幸运在网上找到了),这实际上可以正常工作。但是,尽管我尤其在车轮摩擦值方面作了更多努力,并且仍然希望为AI拥有更平滑的跟随和转向逻辑路径,但我还是建议使用三次贝塞尔曲线样条曲线。我发现Catlike Coding教程非常有趣(我相信很多人都知道这一点,但是下面是有兴趣的人的链接):

https://catlikecoding.com/unity/tutorials/curves-and-splines/

然后,我从本教程中有了使用Spline Walker的想法,将其作为AI的一个航点,并有效地“逗弄”汽车以跟随spline walker,如以下视频所示:

https://www.youtube.com/watch?v=UcA4K2rmX-U#action=share

但是,这是我的大问题-如果我想让汽车跟随花键助步器,同时始终将花键助步器保持在前面,则必须确保花键助步器遵循的“进度”是相对于花键助步器的位置而言的跟随汽车,花键助行器保持在前面,因此汽车不会决定减速和停车。

我一直在寻找可以做到这一点的例子,我不能说我做得太成功了。

这是我当前计算代码片段的进度-我正在尝试通过碰巧共享相同变换坐标的旧路点对象来存储样条线上位置之间的距离:

private void Start()
    {
        Rigidbody rb = chasingCar.GetComponent<Rigidbody>();
        if(path)
        {
            nodes = path.GetComponentsInChildren<Transform>();
        }
        Array.Resize(ref distances, nodes.Length-1);
        for (int i = 0; i < nodes.Length-1; i++)
        {
            //start storing the distances between two successive waypoints on the spline
            distances[i] = Vector3.Distance(nodes[i].position, nodes[i + 1].position);
            totalDistance += distances[i];
        }
        Debug.Log("First distance value is " + distances[0] + " and overall distance est is " + totalDistance);
        Debug.Log("Second distance value is " + distances[1] + " and overall distance est is " + totalDistance);
        Debug.Log("Fifth distance value is " + distances[4] + " and overall distance est is " + totalDistance);
    }

当已将跟踪车及其旧的航路点路径提供给样条线时,这是样条线助步器的更新功能:

Vector3 position;
        if (chasingCar && path)
        {
            float distFromCar = Vector3.Distance(transform.position, chasingCar.transform.position);
            Debug.Log("Distance from car " + distFromCar);
            if(distFromCar < 35)
            {
                //get current spline waypoint
                //int splineIdx = GetSplineIndex(progress);
                int splineIdx = chasingCar.GetComponent<CarEngine>().GetCurrentNodeTarget();
                //declare next spline waypoint
                int splineIdxNext = splineIdx + 1;
                if (path && splineIdxNext == (nodes.Length))
                    splineIdxNext = 0;
                Debug.Log("Current splineIdx " + splineIdx);
                //float currCarDistance = Vector3.Distance(chasingCar.transform.position, nodes[splineIdx].position);
                float currCarDistance = SumSplineProgress(splineIdx);
                float overallDistance = Vector3.Distance(nodes[splineIdx].position, nodes[splineIdxNext].position);
                float currCarSplineProgress = currCarDistance / overallDistance;
                float overallProgress = (currCarDistance) / (totalDistance);
                progress = overallProgress;

            }
            else
            {
                progress += Time.deltaTime / duration;
            }
            Debug.Log("Chasing, current progress: " + progress);
            position = spline.GetPoint(progress);

最后,这是我过去用来计算样条曲线助步器进度的函数:

int GetSplineIndex(float progress)
{
    float curProgress = progress * (totalDistance);
    Debug.Log("Current calculated progress " + curProgress);
    return System.Convert.ToInt32(Mathf.Floor(curProgress));
}

float SumSplineProgress(int index)
{
    float currTotalDistance = 0f;
    for(int i = index; i > -1; i--)
    {
        currTotalDistance += distances[i];
    }
    return currTotalDistance;
}

我可能只是在加重自己的痛苦,但我要说的是,我很困惑。当AI汽车的当前起点和终点之间有更多距离时,我已经接近使样条曲线航路点跳到汽车的前面,但这仍然不是我想要达到的目标。

有人在这里有什么特别的建议吗?提示,方向指示和代码将是很棒的。预先感谢!

UPDATE

是,我正在[[still

正在为此工作!在以前的样条计算代码中,有些逻辑被我认为是错误的,例如:float currCarSplineProgress = currCarDistance / overallDistance;
我已更改为此:

float currCarSplineProgress = (currCarDistance) / currSplineLength;

该部分的想法是检查汽车在整体花键附近行驶的当前曲线上的进度,并相应地定位花键步进器,以便在需要时跳至下一个花键。这是完整的更新代码:

Vector3 position; if (chasingCar && path) { float distFromCar = Vector3.Distance(transform.position, chasingCar.transform.position); Debug.Log("Distance from car " + distFromCar); if(distFromCar < 50) { //get current spline waypoint //int splineIdx = GetSplineIndex(progress); int splineIdx = chasingCar.GetComponent<CarEngine>().GetCurrentNodeTarget()-1; //declare next spline waypoint int splineIdxNext = splineIdx + 1; if(splineIdx == -1) { splineIdx = nodes.Length - 2; splineIdxNext = 0; } if (path && splineIdxNext == (nodes.Length)) splineIdxNext = 0; Debug.Log("Current splineIdx " + splineIdx); //float currCarDistance = GetConvertedDistance(chasingCar.transform.position, nodes[splineIdx].position); float currCarDistance = Vector3.Distance(chasingCar.transform.position, nodes[splineIdx].position); float restDistance = Vector3.Distance(chasingCar.transform.position, nodes[splineIdxNext].position); //float currCarDistance = SumSplineProgress(splineIdx); Debug.Log("currCarDistance " + currCarDistance); //float currSplineLength = Vector3.Distance(nodes[splineIdx].position, nodes[splineIdxNext].position); float currSplineLength = currCarDistance + restDistance; float overallDistance = 0; float nextOverallDist = 0f; if(splineIdx != 0) overallDistance = SumSplineProgress(splineIdx-1); Debug.Log("overallDistance " + overallDistance); float currCarSplineProgNext = 0f; if (splineIdxNext != 1 && splineIdxNext != 0) { nextOverallDist = SumSplineProgress(splineIdxNext - 1); currCarSplineProgNext = (currCarDistance) / nextOverallDist; } Debug.Log("currSplineLength " + currSplineLength); float currCarSplineProgress = (currCarDistance) / currSplineLength; float leading = 10f; if (distFromCar < 20) leading += 15f; float overallProgress; Debug.Log("currCarSplineProgress " + currCarSplineProgress); if (currCarSplineProgress < .7f) { overallProgress = (currSplineLength + (currCarDistance * .3f)) / (totalDistance); } else { Debug.Log("Jumping to next waypoint..."); overallProgress = (nextOverallDist + (currCarDistance * .3f)) / (totalDistance); } Debug.Log("Overall progress " + overallProgress); //if (overallProgress >= 1f) // overallProgress = 0f; progress = overallProgress; } else { progress += Time.deltaTime / duration; } Debug.Log("Chasing, current progress: " + progress); position = spline.GetPoint(progress); } else { position = spline.GetPoint(progress); } transform.localPosition = position;

然而,当汽车前进得足够快时,仍然会发生意想不到的事情-花键助步器将突然跳至上一节中的一个!

enter image description here

任何见解?

我一直在努力开发一款具有能力(但还算不错)的赛车AI的游戏,但我有很多要满足的限制。以下是顺序的条件:1.)AI逻辑和播放器...

您具有使AI跟随沿着样条线移动的目标的正确想法。我相信这就是赛车游戏中大多数AI的工作方式。

为了确保目标始终位于AI之前,将目标的位置设置为样条上AI的位置,并加上与AI移动的速度有关的一些值。

我建议您检出Unity Standard Assets软件包:

https://assetstore.unity.com/packages/essentials/asset-packs/standard-assets-for-unity-2017-3-32351

其中有一个汽车AI系统,它通过跟随沿着样条线移动的目标起作用。

unity3d artificial-intelligence racing
1个回答
0
投票
您具有使AI跟随沿着样条线移动的目标的正确想法。我相信这就是赛车游戏中大多数AI的工作方式。
© www.soinside.com 2019 - 2024. All rights reserved.