【问题标题】:Movement Object and Comparing indetical Vector3 in ArrayListArrayList中的运动对象和比较indetical Vector3
【发布时间】:2019-11-14 15:29:45
【问题描述】:

我正在 Unity 3D 上编写 C# 脚本。 我现在正在做寻路工作。 在 Array List 中已经正确找到了路径,并且 Object 可以按照路径匀速移动。 然后,我想即兴发挥,当找到的路径是直线时,物体会增加它的速度。同时,当路径转弯时,物体会再次降低速度。 在这里,我不知道如何在arrayList 中的直线路径和转弯路径之间进行分组。 感谢你们对我的帮助 :) 这是代码:

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

public abstract class Unit : MonoBehaviour
{
    #region public variables
    public GameObject Astar;
    public bool drawGizmos = false;
    protected float gravity = 9.8f;
    public Transform target;
    public Transform NPC;
    public Vector3 lastTargetPosition;
    public float movementSpeed;
    public float rotationSpeed = 85;
    protected float distanceToPath = 1;
    public Vector2 currentPosition = new Vector2(0, 0);
    protected int spacesMoved = 0;
    // Default action times to 5 second interval
    protected float period = 1f;
    protected float nextActionTime = 1f;
    protected bool isSafeToUpdatePath = false;
    protected int pathFoundCount = 0;
    protected bool isMoving = false;
    protected bool isTargetReached = false;
    #endregion

    #region member variables
    public Vector3[] m_path;
    protected int m_targetIndex;
    protected CharacterController m_characterController;
    private Node lastNodePosition;
    private List<Node> lastPositionNeighbors;
    private Vector3 m_lastKnownPosition;
    private Quaternion m_lookAtRotation;
    private GridSystem m_grid;
    private Coroutine lastRoutine = null;
    private bool preventExtraNodeUpdate = false;
    public Stopwatch timer;
    #endregion

    public virtual void Awake()
    {
        timer = new Stopwatch();
        if (Astar != null)
            m_grid = Astar.GetComponent<GridSystem>();
    }

    public virtual void Start()
    {
        m_characterController = GetComponent<CharacterController>();
        timer.Reset();
        timer.Start();
        PathRequestManager.RequestPath(transform.position, target.position, OnPathFound);
        lastTargetPosition = target.position;
        UnityEngine.Debug.Log("NPC Position : " + transform.position);
        UnityEngine.Debug.Log("Target Position : " + target.position);
    }

    public virtual void Update()
    {

        if (Time.time > nextActionTime) //update path setiap 1f
        {
            nextActionTime += period;
            isSafeToUpdatePath = true;
        }
        else
        {
            isSafeToUpdatePath = false;
        }

        //If we don't check !isMoving the AI may get stuck waiting to update the grid for nextActionTime.

        if (target.position != lastTargetPosition)
        {
            isMoving = true;
            UpdateNodePosition();
            UpdatePath();
            UpdateRotation();
        }

        lastTargetPosition = target.position;

    }

    public void UpdatePath()
    {
        lastNodePosition.walkable = Walkable.Passable;
        PathRequestManager.RequestPath(transform.position, target.position, OnPathFound);
    }

    public virtual void OnPathFound(Vector3[] newPath, bool pathSuccessful)
    {
        if (pathSuccessful)
        {
            pathFoundCount++;
            m_path = newPath;
            m_targetIndex = 0;

            // Stop coroutine if it is already running.
            if (lastRoutine != null)
                StopCoroutine(lastRoutine);

            lastRoutine = StartCoroutine(FollowPath());
        }
    }

    public float time;
    public virtual IEnumerator FollowPath()
    {
        Vector3 currentPath = m_path[0];

        while (true)
        {

            if (Vector3.Distance(transform.position, currentPath) < distanceToPath)
            {
                m_targetIndex++;

                // If we are done with path.
                if (m_targetIndex >= m_path.Length)
                {
                    timer.Stop();
                    UnityEngine.Debug.Log("Time Move : " + timer.ElapsedMilliseconds);
                    isMoving = false;
                    yield break;
                }


                currentPath = m_path[m_targetIndex];
            }
            float Distance = Vector3.Distance(NPC.transform.position, target.transform.position);
            UnityEngine.Debug.Log("Distance : " + Distance);
            // Occurs each frame
            //move follow path
            UpdatePosition(currentPath);

            yield return null;

        }
    }


    public virtual void UpdatePosition(Vector3 destination)
    {
        Node node = m_grid.NodeFromWorldPoint(transform.position);

        Vector3 direction = destination - transform.position;
        movementSpeed = 1;
        transform.Translate(direction.normalized * movementSpeed * Time.deltaTime, Space.World);
        UnityEngine.Debug.Log("Speed NPC : " + movementSpeed);

    }

    public virtual void UpdateRotation()
    {
        m_lastKnownPosition = target.transform.position;
        m_lookAtRotation = Quaternion.LookRotation(m_lastKnownPosition - transform.position);

        if (transform.rotation != m_lookAtRotation)
            transform.rotation = Quaternion.RotateTowards(transform.rotation, m_lookAtRotation, rotationSpeed * Time.deltaTime);
    }


    public void UpdateNodePosition()
    {
        Node node = m_grid.NodeFromWorldPoint(transform.position);

        if (isMoving == false)
        {
            lastPositionNeighbors = m_grid.GetNeighbours(node);
            foreach (Node n in lastPositionNeighbors)
            {
                if (n.walkable != Walkable.Impassable)
                    n.walkable = Walkable.Blocked;
            }
            node.walkable = Walkable.Blocked;
            lastNodePosition = node;
            currentPosition = new Vector2(node.gridX, node.gridY);
            return;
        }

        if (lastNodePosition != null && isMoving)
        {
            preventExtraNodeUpdate = false;
            lastPositionNeighbors = m_grid.GetNeighbours(node);
            lastNodePosition.walkable = Walkable.Passable;
            if (lastPositionNeighbors != null)
                foreach (Node n in lastPositionNeighbors)
                {
                    if (n.walkable != Walkable.Impassable)
                        n.walkable = Walkable.Passable;
                }
            if (!node.Equals(lastNodePosition))
                spacesMoved++;
        }
        else
        {
            node.walkable = Walkable.Blocked;
            lastNodePosition = node;
            currentPosition = new Vector2(node.gridX, node.gridY);
        }



    }

    public void OnDrawGizmos()
    {
        if (!drawGizmos)
            return;

        if (m_path != null)
        {
            for (int i = m_targetIndex; i < m_path.Length; i++)
            {
                Gizmos.color = Color.black;
                Gizmos.DrawCube(m_path[i], Vector3.one);

            }
        }
    }

}

This screenshot after running

【问题讨论】:

  • 您能否举例说明路径数组在路径不直的示例中的外观。我无法理解路径笔直意味着什么。从我所见,您似乎正在网格中移动一个对象。每次在网格上转弯时都想减速吗?
  • drive.google.com/file/d/19eSYUrc4d_YAE79gLZyabD7LyrYzsxJn/… ,,, @SethSetse 谢谢你的回复,从我想要的那张图片中,当物体找到一条直路时,它的速度会增加,但是当道路转弯时,它的速度会再次降低。是的,我使用 Grid 来表示。

标签: c# unity3d


【解决方案1】:

好的。在我看来,为了确定你是否在弯曲的路径上,你所要做的就是检查你要采取的下一步是否直接在玩家面前。您可以在 UpdatePosition 函数中执行此操作。只需检查您要移动的方向是否具有相同的 x 或 z 位置。假设 y 向上并且网格上的所有点都具有相同的 y 位置。在水平移动的情况下,x 将保持不变,在垂直移动的情况下,z 将保持不变。反之亦然。

public virtual void UpdatePosition(Vector3 destination)
{
    Node node = m_grid.NodeFromWorldPoint(transform.position);

    Vector3 direction = destination - transform.position;
    if(destination.x == transform.position.x || destination.z == transform.position.z)
    {
        //Direction is staying the same
        movementSpeed = 1f;
    }else{
        movementSpeed = 0.5f;
    }
    transform.Translate(direction.normalized * movementSpeed * Time.deltaTime, Space.World);
    UnityEngine.Debug.Log("Speed NPC : " + movementSpeed);

}

您应该能够从那里自定义移动速度。如果您在此之后仍然遇到问题,请尝试打印出目标和变换的 (x,y,z) 分量,并查看当路径是直的时它们相似的地方以及路径弯曲时的变化。上面的代码假设 y 永远不会改变。

【讨论】:

  • 我已经尝试过并且它有效,但除了 .toString 之后 .position.z .. 非常感谢.. :) @Seth Setse
  • 有人可以帮忙吗,当 vector3 为负数时我会遇到问题。 operator == 不要认为它是平等的。我该怎么办?
  • @DiahNovianti 你能发布一个新问题并更详细地解释一下吗?
猜你喜欢
  • 1970-01-01
  • 2014-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 2013-08-26
相关资源
最近更新 更多