Why the speed variable have no factor when changing in the inspector the value in run time ? How to update positions and make nonstop moving?

Viewed 49

The main goal is to move the object between the positions with a delay. This is working fine but other things are not working.

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

public class Waypoints : MonoBehaviour
{
    public GameObject objectPrefab;
    public LineRenderer lineRenderer;
    public List<Transform> pointsToMove;
    public float speed;
    public bool go = false;

    private List<GameObject> objectsToMove;
    private List<Vector3> positions;

    void Start()
    {
        objectsToMove = new List<GameObject>();

        //Spawn objects and start movement
        
    }

    private void Update()
    {
        if (go && lineRenderer.positionCount > 0 && CurvedLineRenderer.linesSet)
        {
            positions = GetLinePointsInWorldSpace();

            foreach(Transform objToMove in pointsToMove)
            {
                positions.Add(objToMove.position);
            }

            for (int i = 0; i < 3; i++)
            {
                objectsToMove.Add(Instantiate(objectPrefab, transform.parent));
                StartCoroutine(Move(i));
            }

            go = false;
        }
    }

    private IEnumerator Move(int i)
    {
        //Wait interval
        yield return new WaitForSeconds(i * 10);

        bool stillTraveling = true;
        int pointIndex = 0;
        float threshold = 0.1f;

        while (stillTraveling)
        {
            //Check if close to point
            if (Vector3.Distance(objectsToMove[i].transform.position, positions[pointIndex]) < threshold)
            {
                //Check if can move next point
                if (pointIndex + 1 > positions.Count - 1)
                {
                    stillTraveling = false;
                }
                //If not stop moving
                else
                {
                    pointIndex++;
                }
            }

            //Move towards point
            objectsToMove[i].transform.position = Vector3.MoveTowards(objectsToMove[i].transform.position, positions[pointIndex], speed * Time.deltaTime);

            yield return null;
        }
    }

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

        //the points returned are in world space
        return pointsToMove.ToList();
    }
}

I'm updating once the positions in the Update.

I'm using StartCoroutine once in the Update to send the objects to move between the waypoints with a delay.

private void Update()
        {
            if (go && lineRenderer.positionCount > 0 && CurvedLineRenderer.linesSet)
            {
                positions = GetLinePointsInWorldSpace();
    
                foreach(Transform objToMove in pointsToMove)
                {
                    positions.Add(objToMove.position);
                }
    
                for (int i = 0; i < 3; i++)
                {
                    objectsToMove.Add(Instantiate(objectPrefab, transform.parent));
                    StartCoroutine(Move(i));
                }
    
                go = false;
            }
        }

It's working by sending the objects to move with delay between the waypoints, but now I have some other problems.

Because I'm using StartCoroutine for the delay and because I'm setting the go flag to false then the speed value have no affect on the moving objects at run time and I'm not sure how to solve it so the speed will have a factor affecting the moving objects.

Another problem or not a problem but not sure how to do it is how to Update in run time the positions List ? Here in the Update I'm updating the List once :

positions = GetLinePointsInWorldSpace();
        
                    foreach(Transform objToMove in pointsToMove)
                    {
                        positions.Add(objToMove.position);
                    }

but I want that if the amount of positions in the function GetLinePointsInWorldSpace or/and the amount of pointsToMove have changed to update the positions List at rune time. I could just call this part in the update nonstop but I'm not sure of it will be too expensive ?

Last problem or how to do is how to make the object to move to move between the waypoints non stop over again from the start or moving backward when getting the last waypoint ? Again because using StartCoroutine for the delay everything is happening once.

1 Answers

If you want to move an object from one point to another, you should use Mathf.Sin(). The is using the sine function, and you put in the amount of cycles times Mathf.PI times 2. Here is what you would write:

float period = 2f;

Vector3 a; //the first point the object goes to
Vector3 b; //the second point that the object goes to
void Update()
{
    float cycles = period * Time.time * Mathf.PI;
    float amplitude = Mathf.Sin(cycles);
    Vector3 location = Vector3.Lerp(a, b, amplitude);
    Transform.position = location;
}

I then use Vector3.Lerp to interpolate between point a and point b. This isn’t what you were doing, but it is a much simpler way you can do it.

Vector3 a; //the first point the object goes to
Vector3 b; //the second point that the object goes to
void Update()
{
    float cycles = period * Time.time;
    Vector3 location = Vector3.Lerp(a, b, cycles);
    Transform.position = location;
}

This one is for bringing the object just strait to point b and not back.

If you want there to be a delay between when it moves, here is the script:

float period = 2f;

float waitTime;
bool AtoB = true;
Vector3 a; //the first point the object goes to
Vector3 b; //the second point that the object goes to
void Start()
{
    StartCoroutine(“Oscillator”);
}
IEnumerator Oscillator
{
    float amplitude;
    if (AtoB)
    {
        amplitude += Time.deltaTime * period;
    }
    else
    {
        amplitude -= Time.deltaTime * period;
    }
    amplitude = Mathf.Clamp(amplitude, 0, 1);
    Vector3 location = Vector3.Lerp(a, b, amplitude);
    Transform.position = location;
    if (amplitude == 1)
    {
        AtoB = false;
        yield return new WaitForSeconds(waitTime);
    }
    if else (amplitude == 0)
    {
        AtoB = true;
        yield return new WaitForSeconds(waitTime);
    }
    else
    {
        yield return false;
    }
}
Related