Unity3D运动问题(基于网格的寻路)

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

我目前正在尝试将角色移动到鼠标目标上。自2周以来,我做了很多研究,虽然感觉很接近目标,但我仍然很努力。在按下播放之前,我会收到以下警告:

Assets\Scripts\Worldmaps\Movement.cs(11,12): warning CS0649: Field 'Movement.path' is never assigned to, and will always have its default value null

并且当我按下播放键时,单击任何节点后,我都会收到此错误:

NullReferenceException: Object reference not set to an instance of an object Movement.Update () (at Assets/Scripts/Worldmaps/Movement.cs:24)

这里是代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour
{
    private const float speed = 10f;
    private int targetIndex;
    Vector3[] path;
    private Pathfinding pathfinding;

    void Awake()
    {
        pathfinding = GetComponent<Pathfinding>();
    }

    private void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Vector3 target = GetMouseWorldPosition();
            pathfinding.StartFindPath(transform.position, target);
            targetIndex = 0;
            Vector3 finalPath = path[0];
            while(true)
            {
                if(transform.position == finalPath)
                {
                    targetIndex++;
                    if(targetIndex >= path.Length)
                    {
                        break;
                    }
                    finalPath = path[targetIndex];
                }
                transform.position = Vector3.MoveTowards(transform.position, finalPath, speed * Time.deltaTime);
            }
            Debug.Log(target);
        }
    }

    public static Vector3 GetMouseWorldPosition()
    {
        Vector3 clickPosition = new Vector3();
        clickPosition.y = 0;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if(Physics.Raycast(ray, out hit))
        {
            clickPosition = hit.point;
        }
        return clickPosition;
    }
}

寻路脚本没有任何问题,因为它在寻路脚本中将public Transform character;Update() FindPath(character.position, target)一起使用时,可以很好地更新字符和目标之间的路径。

即使我是一个初学者并且缺乏技能,我也知道为其他人编写代码可能很烦人,因此老实说也欢迎提出建议!寻路可能不是初学者最容易开始的事情,但这是我真正想要继续的项目的基础!

以防万一,如果您需要探路代码的参考(Sebastian Lague教程):

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Pathfinding : MonoBehaviour
{
    AGrid grid;

    void Awake()
    {
        grid = GetComponent<AGrid>();
    }

    public void StartFindPath(Vector3 startPos, Vector3 targetPos)
    {
        StartCoroutine(FindPath(startPos, targetPos));
    }

    IEnumerator FindPath(Vector3 startPos, Vector3 targetPos)
    {
        Node startNode = grid.NodeFromWorldPoint(startPos);
        Node targetNode = grid.NodeFromWorldPoint(targetPos);

        Heap<Node> openSet = new Heap<Node>(grid.MaxSize);
        HashSet<Node> closedSet = new HashSet<Node>();
        openSet.Add(startNode);

        while(openSet.Count > 0)
        {
            Node currentNode = openSet.RemoveFirst();
            closedSet.Add(currentNode);

            if(currentNode == targetNode)
            {
                RetracePath(startNode, targetNode);
                break;
            }

            foreach(Node neighbour in grid.GetNeighbours(currentNode))
            {
                if(!neighbour.walkable || closedSet.Contains(neighbour))
                {
                    continue;
                }

                int newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour);
                if(newMovementCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                {
                    neighbour.gCost = newMovementCostToNeighbour;
                    neighbour.hCost = GetDistance(neighbour, targetNode);
                    neighbour.parent = currentNode;

                    if(!openSet.Contains(neighbour))
                    {
                        openSet.Add(neighbour);
                    }
                    else
                    {
                        openSet.UpdateItem(neighbour);
                    }
                }
            }
        }
        yield return null;
    }

    void RetracePath(Node startNode, Node endNode)
    {
        List<Node> path = new List<Node>();
        Node currentNode = endNode;

        while(currentNode != startNode)
        {
            path.Add(currentNode);
            currentNode = currentNode.parent;
        }
        path.Add(startNode);
        path.Reverse();
    }

    int GetDistance(Node nodeA, Node nodeB)
    {
        int dstX = Mathf.Abs(nodeA.gridX - nodeB.gridX);
        int dstZ = Mathf.Abs(nodeA.gridZ - nodeB.gridZ);

        if(dstX > dstZ)
        {
            return 14 * dstZ + 10 * (dstX - dstZ);
        }
        return 14 * dstX + 10 * (dstZ - dstX);
    }
}

谢谢您!

花枪:)

c# unity3d multidimensional-array path-finding
1个回答
1
投票

使用前必须实例化Vector3 []路径数组。因此,在Awake()中,只需使用以下方法将其实例化:

path = new Vector3[<write the length of the array here>];

例如:

path = new Vector3[5];

如果不确定数组中对象的长度或数量经常变化,最好使用List而不是数组。

© www.soinside.com 2019 - 2024. All rights reserved.