1
\$\begingroup\$
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class Waypoints : MonoBehaviour
{
    public GameObject objToMove;
    public LineRenderer lineRenderer;
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;
    public float rotSpeed;
    public bool random = false;
    public int currentCurvedLinePointIndex;

    private Vector3[] pos;
    private int index = 0;
    private bool goForward = true;
    private List<GameObject> curvedLinePoints = new List<GameObject>();
    private int numofposbetweenpoints;
    private bool getPositions = false;

    // Start is called before the first frame update
    void Start()
    {
        var parent = GameObject.Find("Moving Object Parent");
        objToMove = Instantiate(objToMove, parent.transform);
        objToMove.name = "Platfrom";

        curvedLinePoints = GameObject.FindGameObjectsWithTag("Curved Line Point").ToList();

        if (curvedLinePoints != null && curvedLinePoints.Count > 0)
        {
            //objToMove.transform.rotation = curvedLinePoints[1].transform.rotation;
        }
    }

    Vector3[] GetLinePointsInWorldSpace()
    {
        var 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 (lineRenderer.positionCount > 0 && getPositions == false && CurvedLineRenderer.linesSet)
        {
            pos = GetLinePointsInWorldSpace();

            numofposbetweenpoints = curvedLinePoints.Count;

            if (moveToFirstPositionOnStart == true)
            {
                //objToMove.transform.position = pos[index];
            }

            getPositions = true;
        }

        if (go == true && lineRenderer.positionCount > 0 && CurvedLineRenderer.linesSet)
        {
            pos = GetLinePointsInWorldSpace();
            Move();
        }
    }

    int counter = 0;
    int c = 1;
    void Move()
    {
        Vector3 newPos = objToMove.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++;
                        counter++;
                        if (counter == numofposbetweenpoints)
                        {
                            c++;

                            counter = 0;
                        }
                        if (c == curvedLinePoints.Count - 1)
                        {
                            c = 0;
                        }
                    }
                    else { index--; goForward = false; }
                }
                else
                { // going backwards:
                    bool atFirstOne = index <= 0;
                    if (!atFirstOne)
                    {
                        index--;

                        counter++;
                        if (counter == numofposbetweenpoints)
                        {
                            c++;

                            counter = 0;
                        }
                        if (c == curvedLinePoints.Count - 1)
                        {
                            c = 0;
                        }
                    }
                    else { index++; goForward = true; }
                }
            }
            else
            {
                stillTraveling = false;
            }
        }

        objToMove.transform.position = newPos;
    }
}

Now it's working fine with the single object the variable objToMove but I want to turn the variable either to a List or to Array like objsToMove and then using some timer or a coroutine to fire each X seconds for example every 3 seconds to start moving the next objToMove between the waypoints from the List/Array.

\$\endgroup\$
0

1 Answer 1

0
\$\begingroup\$

Your approach is conceptually backwards. Waypoints should generally be defined in a basic data structure, and objects that want to follow the waypoints should reference the set of waypoints. Objects move themselves while following waypoints; waypoints do not move objects.

Here's a simple example:

public class Waypoints : MonoBehaviour {
    //with this approach, you use GameObjects to represent your waypoints 
    //(they can be empty if you want the waypoint to be invisible)
    [SerializeField] private List<Transform> waypoints;
    
    public int Count => waypoints.Count;
    public Vector3 GetWaypoint(int index) {
        return waypoints[index].position;
    }
}

public class WaypointFollower : MonoBehaviour {
    [SerializeField] private Waypoints waypoints;
    [SerializeField] private float speed = 5f;

    private int waypointIndex = 0;

    void Update() {
        Vector3 waypoint = waypoints.GetWaypoint(waypointIndex);
        //movement
        float distance = speed * Time.deltaTime;
        transform.position = Vector3.MoveTowards(transform.position, waypoint, distance);

        //check if we've reached the waypoint
        float threshold = .5f; //how close is considered having reached the waypoint
        if (Vector3.Distance(transform.position, waypoint) < threshold) {
            //wraps back to 0 when we reach last waypoint
            waypointIndex = (waypointIndex + 1) % waypoints.Count;
        }
    }
}

This way, any number of moving objects can independently follow the waypoints. The waypoints do not have to know about or manage state for any of the moving objects; those objects can manage their own state.

\$\endgroup\$
2
  • \$\begingroup\$ Or the second mono should be on the moving object prefab so if I have 5 moving objects each one of them will have his own control ? I tried it too and getting the same error. but should I put the second mono on the prefab of the moving object/s ? \$\endgroup\$
    – Daniel Lip
    Commented Apr 21, 2021 at 7:00
  • \$\begingroup\$ How can I make that it will move back only if a flag is set to true when running the game? I added a flag name goBack on the WaypointFollower script and at this place I want it to move back only if the flag is true if the flag false move between all the waypoints but stop at the last one and don't move back. waypointIndex = (waypointIndex + 1) % waypoints.Count; \$\endgroup\$
    – Daniel Lip
    Commented Apr 21, 2021 at 22:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .