0
\$\begingroup\$

Now it's moving from the first position the last position and then in the end it's moving to the first position and then moving forward on all positions again and so on.

I want to use a flag bool variable that if it's true when the object to move on the waypoints will get to the last position it will then travel backward reverse on the positions and when it will get to the first one it will start moving forward again and so on like a ping pong. and if the bool flag is false it will be like now.

I'm not sure how to handle the line :

index = (index + 1) % pos.Length;

Not sure what the percentage % does in this line.

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

public class MoveOnCurvedLine : MonoBehaviour
{
    public LineRenderer lineRenderer;
    public GameObject objectToMove;
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;

    private Vector3[] positions;
    private Vector3[] pos;
    private int index = 0;

    // Start is called before the first frame update
    void Start()
    {
        pos = GetLinePointsInWorldSpace();

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

    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()
    {
        Vector3 newPos = objectToMove.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
            {
                index = (index + 1) % pos.Length;
            }
            else
            {
                stillTraveling = false;
            }
        }

        objectToMove.transform.position = newPos;
    }   
}

I tried to do it this way :

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

public class MoveOnCurvedLine : MonoBehaviour
{
    public LineRenderer lineRenderer;
    public GameObject objectToMove;
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;

    private Vector3[] positions;
    private Vector3[] pos;
    private int index = 0;
    private bool isreverse = false;

    // Start is called before the first frame update
    void Start()
    {
        pos = GetLinePointsInWorldSpace();

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

    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();
        }

        if (index == pos.Length - 1)
        {
            System.Array.Reverse(pos);
            isreverse = true;
        }
    }

    void Move()
    {
        Vector3 newPos = objectToMove.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 (isreverse)
            {
                if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
                {
                    index --;// % pos.Length;
                }
                else
                {
                    stillTraveling = false;
                }
            }
            else
            {
                if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
                {
                    index = (index + 1) % pos.Length;
                }
                else
                {
                    stillTraveling = false;
                }
            }
        }

        objectToMove.transform.position = newPos;
    }
}

And it's moving in reverse when it's getting to the last position but there is a problem :

Each time it's getting to the last position the object to move is stuck and shaking like it's trying to move back to forward but stay in place and shaking and then after few seconds it's starting moving back in reverse. Why it happens ?

\$\endgroup\$
1
  • 2
    \$\begingroup\$ "Not sure what the percentage % does in this line." - so to find out, you typed "percent sign in C#" into your favourite search engine and found existing answers that explain it, right? You ask a lot of questions here that you could answer for yourself faster with just a little legwork, or working your way through a tutorial to understand more about the tools you're using. I strongly recommend getting into this habit to accelerate your development and make better use of the resources you have here. \$\endgroup\$ – DMGregory Oct 28 '20 at 21:17
1
\$\begingroup\$

In C# % is to modulo/modulus operator. Essentially what it does is if left value exceeds the right value, subtract the right value until it is less than the right. Not the best explanation but as @DMGregory said, you can/should look it up if you want to better understand it's meaning. I would strongly recommend doing so since it is very important when working with Lists and Arrays.

As for your script issue. Thank you for posting what you tried, that is pretty rare these days. It looks like your problem comes from calling System.Arrays.Reverse() and switching the increment value of your index. Basically you are going backwards in a reversed list (so forwards again). That's probably where your code is freaking out. You should be able to find these issues using C# break points (seriously look this up, it is a life saver) and Unity debug statements.

I've mocked up a quick untested solution that should hopefully help but you may need to tweak it a bit to your liking.

public class MoveOnCurvedLine : MonoBehaviour
{
    #region Nested Classes

    public enum PlayMode
    {
        OneShot,
        Loop,
        PingPong
    }

    #endregion

    #region Fields

    [Header("Linked Scene Objects")]
    public LineRenderer lineRenderer;
    public GameObject objectToMove;

    [Header("Settings")]
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;
    public PlayMode playmode = PlayMode.Loop;

    private Vector3[] pos;
    private int index = 0;
    public bool isForward = true;

    #endregion

    #region MonoBehaviour Methods

    // Start is called before the first frame update
    private void Start()
    {
        pos = GetLinePointsInWorldSpace();
        index = isForward ? 0 : pos.Length - 1;

        if (moveToFirstPositionOnStart)
        {
            objectToMove.transform.position = pos[index];
        }
    }

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

    #endregion

    #region Private Methods

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

    private void Move()
    {
        Vector3 newPos = objectToMove.transform.position;
        float distanceToTravel = speed * Time.deltaTime;

        while (go && distanceToTravel > 0.0001f)
        {
            Vector3 oldPos = newPos;
            Vector3 nextPos = pos[index];
            newPos = Vector3.MoveTowards(oldPos, nextPos, distanceToTravel);
            
            distanceToTravel -= Vector3.Distance(newPos, oldPos);

            if (newPos == nextPos) // Vector3 comparison is approximate so this is ok
            {
                if (isForward)
                {
                    index--;

                    switch (playmode)
                    {
                        case PlayMode.Loop:
                            index = (index + pos.Length) % pos.Length;
                            break;
                        case PlayMode.OneShot:
                            if (index < 0)
                            {
                                go = false;
                                index = 0;
                            }
                            break;
                        case PlayMode.PingPong:
                            if (index < 0)
                            {
                                isForward = !isForward;
                                index = 0;
                            }
                            break;
                    }
                }
                else
                {
                    index++;

                    switch (playmode)
                    {
                        case PlayMode.Loop:
                            index = index % pos.Length;
                            break;
                        case PlayMode.OneShot:
                            if (index >= pos.Length)
                            {
                                go = false;
                                index = pos.Length - 1;
                            }
                            break;
                        case PlayMode.PingPong:
                            if (index >= pos.Length)
                            {
                                isForward = !isForward;
                                index = pos.Length - 1;
                            }
                            break;
                    }
                }
            }
        }

        objectToMove.transform.position = newPos;
    }

    #endregion
}
\$\endgroup\$
2
  • \$\begingroup\$ The whole project is freezing when running. When using a breakpoint I see on the line : while (distanceToTravel > 0) that the distanceToTravel value is some long number with E error. \$\endgroup\$ – Daniel Lip Oct 29 '20 at 21:30
  • \$\begingroup\$ Looks like a simple floating point error. You will run into those a lot. Usually you just need to check if a value is < than something like 0.0001f rather that == 0. I'll update the answer to fix that bug. I also added a check to see if go is enabled to fix a bug that locked the UI when a oneshot animation is finished. \$\endgroup\$ – Benjamin Danger Johnson Nov 6 '20 at 3:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.