【问题标题】:Why the objects to move are moving to each other and not following each other by 3 seconds space delay?为什么要移动的物体相互移动而不是相互跟随 3 秒的空间延迟?
【发布时间】:2020-10-30 15:15:21
【问题描述】:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class MoveOnCurvedLines : MonoBehaviour
{
    public LineRenderer lineRenderer;
    public List<GameObject> objectsToMove = new List<GameObject>();
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;

    private Vector3[] positions;
    private Vector3[] pos;
    private int index = 0;
    private bool goForward = true;
    private List<GameObject> objectsToMoveCopy = new List<GameObject>();

    // Start is called before the first frame update
    void Start()
    {
        objectsToMove = GameObject.FindGameObjectsWithTag("New Prefab").ToList();

        pos = GetLinePointsInWorldSpace();

        if (moveToFirstPositionOnStart == true)
        {
            for (int i = 0; i < objectsToMove.Count; i++)
            {
                objectsToMove[i].transform.position = pos[index];
            }
        }

        StartCoroutine(AddNew());
    }

    Vector3[] GetLinePointsInWorldSpace()
    {
        positions = new Vector3[lineRenderer.positionCount];
        //Get the positions which are shown in the inspector 
        lineRenderer.GetPositions(positions);


        //the points returned are in world space
        return positions;
    }

    // Update is called once per frame
    void Update()
    {
        if (go == true)
        {
            Move();
        }
    }

    void Move()
    {
        for (int i = 0; i < objectsToMoveCopy.Count; i++)
        {
            Vector3 newPos = objectsToMoveCopy[i].transform.position;
            float distanceToTravel = speed * Time.deltaTime;

            bool stillTraveling = true;
            while (stillTraveling)
            {
                Vector3 oldPos = newPos;
                newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);
                distanceToTravel -= Vector3.Distance(newPos, oldPos);
                if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
                {
                    // when you hit a waypoint:
                    if (goForward)
                    {
                        bool atLastOne = index >= pos.Length - 1;
                        if (!atLastOne) index++;
                        else { index--; goForward = false; }
                    }
                    else
                    { // going backwards:
                        bool atFirstOne = index <= 0;
                        if (!atFirstOne) index--;
                        else { index++; goForward = true; }
                    }
                }
                else
                {
                    stillTraveling = false;
                }
            }

            objectsToMoveCopy[i].transform.position = newPos;
        }
    }

    IEnumerator AddNew()
    {
        WaitForSeconds waitThreeSeconds = new WaitForSeconds(3);

        foreach (var objToMove in objectsToMove)
        {
            yield return waitThreeSeconds;
            objectsToMoveCopy.Add(objToMove);
        }
    }
}

我使用 StartCoroutine 和 AddNew 方法每 3 秒在路点之间移动每个对象。

逻辑:

  • 要从列表中移动的第一个对象是从第一个位置开始移动。

  • 3 秒后,要从列表中移动的第二个对象将从第一个位置开始移动。

  • 目标是让每个对象在他之前的第一个移动对象之后 3 秒后从第一个位置开始移动,所以最后我会让这些对象以 3 秒的间隔移动。

问题:

  • 第一个对象在从第一个位置 3 秒后开始移动,然后第二个和第三个对象开始移动,但是从最后一个移动的对象开始,其他已经移动的对象与其他对象合并最后我有一组所有要移动的物体都一起移动。

如果它们反向移动,我想要的行为相同。

【问题讨论】:

  • 您能否更详细地解释一下究竟是什么问题。很难理解一切。我唯一得到的是,它们似乎都在延迟 3 秒后移动到同一点,而不是延迟 3 秒后移到彼此?

标签: c# unity3d


【解决方案1】:

您的对象合并,因为您只有一个对象目标位置的索引,这意味着所有对象都朝着同一个点移动,而不是每个对象都朝着路径上各自的下一个点移动。一旦第一个对象转身并向后运行,这就会导致合并。

最好将你的逻辑分成两个类,否则你必须分别跟踪每个对象的路径,这意味着你需要一个 int[] indices 来表示每个对象的当前目标位置,另一个数组用于goForward bools 等为您介绍的每个新属性。

控制器:

public class MovementController : MonoBehaviour
{
    [SerializeField]
    private LineRenderer lineRenderer;
    [SerializeField]
    private float speed;
    [SerializeField]
    private bool moveToFirstPositionOnStart;

    public List<MoveOnCurvedLines> movingObjects = new List<MoveOnCurvedLines>();

    void Start()
    {
        Vector3[] positions = GetPositions();

        movingObjects = GameObject.FindGameObjectsWithTag("New Prefab").Select(go => go.GetComponent<MoveOnCurvedLines>().ToList();

        foreach (MoveOnCurvedLines obj in movingObjects)
        {
            obj.Init(positions, speed, moveToFirstPositionOnStart);
        }

        StartCoroutine(TriggerObjects(false));
    }

    Vector3[] GetPositions()
    {
        Vector3[] positions = new Vector3[lineRenderer.positionCount];
        //Get the positions which are shown in the inspector 
        lineRenderer.GetPositions(positions);
        return positions;
    }

    IEnumerator TriggerObjects(bool delayFirstObject)
    {
        WaitForSeconds waitThreeSeconds = new WaitForSeconds(3);

        if (delayFirstObject)
            yield return waitThreeSeconds;

        foreach (MoveOnCurvedLines obj in movingObjects)
        {
            obj.StartMoving();
            yield return waitThreeSeconds;
        }
    }
}

运动逻辑:

public class MoveOnCurvedLines : MonoBehaviour
{
    private Transform myTransform;
    private bool initialized;

    private Vector3[] pos;
    private int posIndex = 0;
    private float speed;
    private bool goForward = true;
    private Coroutine moving;

    public void Init(Vector3[] positions, float speed, bool instantlyMoveToFirstPosition)
    {
        myTransform = transform;
        pos = positions;
        this.speed = speed;
        if (instantlyMoveToFirstPosition)
            myTransform.position = positions[0];
        initialized = true;
    }

    public void StartMoving()
    {
        if (initialized && moving == null)
            moving = StartCoroutine(Move());
    }

    public void StopMoving()
    {
        if (moving != null)
        {
            StopCoroutine(moving);
            moving = null;
        }
    }

    private IEnumerator Move()
    {
        while (true)
        {
            Vector3 newPos = myTransform.position;
            float distanceToTravel = speed * Time.deltaTime;

            bool stillTraveling = true;
            while (stillTraveling)
            {
                Vector3 oldPos = newPos;
                newPos = Vector3.MoveTowards(oldPos, pos[posIndex], distanceToTravel);
                distanceToTravel -= Vector3.Distance(newPos, oldPos);
                if (newPos == pos[posIndex]) // Vector3 comparison is approximate so this is ok
                {
                    // when you hit a waypoint:
                    if (goForward)
                    {
                        bool atLastOne = posIndex >= pos.Length - 1;
                        if (!atLastOne)
                        {
                            posIndex++;
                        }
                        else
                        {
                            posIndex--;
                            goForward = false;
                        }
                    }
                    else
                    { // going backwards:
                        bool atFirstOne = posIndex <= 0;
                        if (!atFirstOne)
                        {
                            posIndex--;
                        }
                        else
                        {
                            posIndex++; 
                            goForward = true;
                        }
                    }
                }
                else
                {
                    stillTraveling = false;
                }
            }

            myTransform.position = newPos;
        }
    }
}

MovementController 仅提供所有对象共享的必要数据(例如路径),但每个MoveOnCurvedLines 对象都会独立跟踪其进度。

优化:

  • 我将transform 缓存在myTransform 中,因为Unity 的transform 每次调用GetComponent&lt;Transform&gt;() 都会产生不必要的开销。
  • 移动是在协程中完成的,而不是在 Update 中,因为不需要每帧检查 n 个 go 布尔值 n 个对象不移动。
  • 我将您的public 字段更改为private 进行序列化,因为最好的做法是尽可能限制访问。如果您需要从项目中的另一个脚本访问它们,只需再次将它们设为 public。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 2014-05-22
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2015-07-31
    相关资源
    最近更新 更多