Unity A *寻路项目:重新使角色向相反的方向移动

时间:2015-11-30 21:51:38

标签: unity3d path-finding a-star

请观看此简短视频以查看问题。一旦有大约23个字符,它们就开始向不同的方向移动。请帮助我,我尽我所能搜索了几天并尝试了不同的寻路方法,但没有成功。

http://screencast.com/t/sUx9O0I9GQ

我的设置是一个网格,字符有一个附加默认配置组件的AIPath。这一定是可能的,因为我在压力测试视频中看到了它:https://www.youtube.com/watch?v=htoen7x3LuQ

这行代码会导致麻烦:

seeker.StartPath (transform.position,target.transform.position, OnPathComplete);

完整的背景

public void Start () {
    InvokeRepeating ("searchPath", 1.0f, 1.0f);
    searchPath ();
}

public void searchPath() {
    GameObject target = GameObject.Find ("Target");
    seeker = GetComponent<Seeker>();
    controller = GetComponent<CharacterController>();
    //Start a new path to the targetPosition, return the result to the OnPathComplete function
    seeker.StartPath (transform.position,target.transform.position, OnPathComplete);
}

public void OnPathComplete (Path p) {
    Debug.Log ("Yay, we got a path back. Did it have an error? "+p.error);
    if (!p.error) {
        path = p;
        //Reset the waypoint counter
        currentWaypoint = 0;
    }
}

public void Update () {
    if (path == null) {
        //We have no path to move after yet
        return;
    }
    if (currentWaypoint >= path.vectorPath.Count) {
        Debug.Log ("End Of Path Reached");
        Destroy(gameObject);
        return;
    }
    //Direction to the next waypoint
    Vector3 dir = (path.vectorPath[currentWaypoint]-transform.position).normalized;
    dir *= speed * Time.deltaTime;
    controller.SimpleMove (dir);
    //Check if we are close enough to the next waypoint
    //If we are, proceed to follow the next waypoint
    if (Vector3.Distance (transform.position,path.vectorPath[currentWaypoint]) < nextWaypointDistance) {
        currentWaypoint++;
        return;
    }
}

正如标题所说,它的Aron Granbergs寻路项目http://arongranberg.com/astar/

谢谢

2 个答案:

答案 0 :(得分:1)

好吧,我在 Aron Granbergs 中玩过这个美妙的AStar库,我必须说使用所有说明和他教程中的所有代码......工作得很好。< / p>

我已经在他的教程中使用了 Aron 提供的代码,添加了您添加的Destroy指向教程的链接: http://arongranberg.com/astar/docs/getstarted.php

代码:

using UnityEngine;
using Pathfinding;

public class PlayerScript : MonoBehaviour {

    public Vector3 targetPosition;
    private Seeker seeker;
    private CharacterController controller;
    //The calculated path
    public Path path;
    //The AI's speed per second
    public float speed = 100;
    //The max distance from the AI to a waypoint for it to continue to the next waypoint
    public float nextWaypointDistance = 3;
    //The waypoint we are currently moving towards
    private int currentWaypoint = 0;
    public void Start()
    {
        seeker = GetComponent<Seeker>();
        controller = GetComponent<CharacterController>();
        //Start a new path to the targetPosition, return the result to the OnPathComplete function
        targetPosition = GameObject.Find("Target").transform.localPosition;
        seeker.StartPath(transform.position, targetPosition, OnPathComplete);
    }
    public void OnPathComplete(Path p)
    {
        Debug.Log("Yay, we got a path back. Did it have an error? " + p.error);
        if (!p.error)
        {
            path = p;
            //Reset the waypoint counter
            currentWaypoint = 0;
        }
    }
    public void Update()
    {
        if (path == null)
        {
            //We have no path to move after yet
            return;
        }
        if (currentWaypoint >= path.vectorPath.Count)
        {
            Debug.Log("End Of Path Reached");
            Destroy(gameObject);
            return;
        }
        //Direction to the next waypoint
        Vector3 dir = (path.vectorPath[currentWaypoint] - transform.position).normalized;
        dir *= speed * Time.deltaTime;
        controller.SimpleMove(dir);
        //Check if we are close enough to the next waypoint
        //If we are, proceed to follow the next waypoint
        if (Vector3.Distance(transform.position, path.vectorPath[currentWaypoint]) < nextWaypointDistance)
        {
            currentWaypoint++;
            return;
        }
    }
}

我的Player附加了SeekerCharacterControllerRigidbody。我正在使用Sphere primitve和你模拟运动一样。

我还添加了Duplicator来逐个实例化它们:

<强> PlayerDuplicator:

using UnityEngine;
using System.Collections;

public class PlayerDuplicator : MonoBehaviour
{

    public GameObject PlayerPrefab;
    public uint HowMany = 50;
    public float Interval = 0.2f;
    public Vector3 InstantiatePosition;

    // Use this for initialization
    void Start ()
    {
        StartCoroutine("DeployPlayers");
    }

    // Update is called once per frame
    void Update () {

    }

    public IEnumerator DeployPlayers()
    {
        if (PlayerPrefab == null) yield break;
        while (HowMany > 0)
        {
            var player = Instantiate(PlayerPrefab);
            player.transform.position = InstantiatePosition;
            HowMany--;
            yield return new WaitForSeconds(Interval);
        }
        yield return null;
    }
}

我的结果在这里: http://screencast.com/t/auTh0uvX

请注意我没有使用Simple Smooth Modifier所以我的球体在其中一条曲线上优雅地击中障碍物。

我已经使用动态路径查找和您的部分代码进行了测试:

public void Start()
{
    InvokeRepeating("searchPath", 1.0f, 1.0f);
    searchPath();
}

public void searchPath()
{
    GameObject target = GameObject.Find("Target");
    seeker = GetComponent<Seeker>();
    controller = GetComponent<CharacterController>();
    //Start a new path to the targetPosition, return the result to the OnPathComplete function
    seeker.StartPath(transform.position, target.transform.position, OnPathComplete);
}

结果看起来很好,但我可以看到你有时玩家可能会失去一段时间的路径。 它可能确实依赖于单个线程的性能。

我的输出有100名玩家, Instantiate 每次 0.05s

http://www.screencast.com/users/battlefist/folders/Jing/media/9039b000-cf61-4d11-9a91-573b98e6fd91

答案 1 :(得分:1)

我得到了A *寻路项目作者Aron的回复。

  

您好

     

这是由于寻路系统的负荷很高。代理可能   在某个时刻请求路径,但是因为它需要一些时间   对于要计算的路径,代理将在到达时移动   结果回来了。 AIPath脚本试图解决这个问题(假设是   nearestOnPathCheck字段已启用)但它无法始终执行此操作。   解决方案是减少寻路系统和负载   游戏。首先,确保启用了多线程(A * Inspector    - &GT;设置),也可能最好关闭显示较大图形的图形,因为绘图非常慢并且会减少   fps显着。你也可以增加   pickNextWaypointDistance和AIPath上的forwardLook字段   脚本,这将减少这种情况发生的可能性。

添加光线投射修改器将进一步提高性能。 免费版仅支持一个主题,专业版最多支持8个。