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

public class WaypointsFollower : MonoBehaviour
{
    public float speed;
    public Waypoints waypoints;
    public Transform capsule;
    public bool go;
    public bool goForward;
    public float rotationSpeed;

    private int index = 0;
    private int counter = 0;
    private int c = 0;
    private List<GameObject> curvedLinePoints = new List<GameObject>();

    public int numofposbetweenpoints;

    private bool getonce;
    private bool getBackwardIndexOnce = true;

    private void Start()
    {
        waypoints = GameObject.Find("Waypoints").GetComponent<Waypoints>();

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

        if(waypoints.moveInReverse == false)
        {
            goForward = true;
        }
        else
        {
            goForward = false;
        }

        if(goForward)
        {
            index = 0;
        }
    }

    private void Update()
    {
        if (getonce == false)
        {
            numofposbetweenpoints = curvedLinePoints.Count;

            getonce = true;
        }

        if (go == true && waypoints.lineRendererPositions.Count > 0)
        {
            if(goForward == false && getBackwardIndexOnce)
            {
                index = waypoints.lineRendererPositions.Count - 1;

                getBackwardIndexOnce = false;
            }

            Move();
        }
    }

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

        bool stillTraveling = true;
        while (stillTraveling)
        {
            Vector3 oldPos = newPos;

            // error exception out of bound on line 55 to check !!!!!
            newPos = Vector3.MoveTowards(oldPos, waypoints.lineRendererPositions[index], distanceToTravel);

            distanceToTravel -= Vector3.Distance(newPos, oldPos);

            if (newPos == waypoints.lineRendererPositions[index]) // Vector3 comparison is approximate so this is ok
            {
                // when you hit a waypoint:
                if (goForward)
                {
                    bool atLastOne = index >= waypoints.lineRendererPositions.Count - 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;
            }
        }

        transform.position = newPos;
    }

    private void RotateTo()
    {
        // Determine which direction to rotate towards
        Vector3 targetDirection = -capsule.position;

        // The step size is equal to speed times frame time.
        float singleStep = rotationSpeed * Time.deltaTime;

        // Rotate the forward vector towards the target direction by one step
        Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);

        // Draw a ray pointing at our target in
        Debug.DrawRay(capsule.position, newDirection, Color.red);

        // Calculate a rotation a step closer to the target and applies rotation to this object
        capsule.rotation = Quaternion.LookRotation(newDirection);
    }
}

The transform is moving along the waypoints but I want that the capsule to rotate facing each numofposbetweenpoints.

There are a lot of waypoints over 4000 more or less but there are only 10 numofposbetweenpoints. This screenshot will clear it. The waypoints are the linerenderer positions and the numofposbetweenpoints are the cubes that connect each line of the line renderer lines.

Clear image

In the screenshot, the big cube is the transform in the script the transform is moving along the ping lines that are the linerenderer positions. The small cubes in the background are the points where the linerenderer lines are connected at.

I want the capsule to rotate smoothly looking at the numofposbetweenpoints(Small Cubes) each time the transform is moving the capsule should rotate smoothly looking at the next numofposbetweenpoints. there are only 10 of numofposbetweenpoints.

This is the rotation part at the bottom :

private void RotateTo()
        {
            // Determine which direction to rotate towards
            Vector3 targetDirection = -capsule.position;
    
            // The step size is equal to speed times frame time.
            float singleStep = rotationSpeed * Time.deltaTime;
    
            // Rotate the forward vector towards the target direction by one step
            Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);
    
            // Draw a ray pointing at our target in
            Debug.DrawRay(capsule.position, newDirection, Color.red);
    
            // Calculate a rotation a step closer to the target and applies rotation to this object
            capsule.rotation = Quaternion.LookRotation(newDirection);
        }

At this line it's missing the next small cube each time :

Vector3 targetDirection = -capsule.position;

I have the number of small cubes numofposbetweenpoints but how do I get a reference to each small cube and make the numofposbetweenpoints index increase each time?

At line 50 I'm doing :

numofposbetweenpoints = curvedLinePoints.Count;

curvedLinePoints is a List but I'm not sure how to do the rotation to the GameObjects in the List.

This is what I did so far I think the rotation is working but not as I wanted :

At the top I added :

private int rotationIndex = 0;

Then in the RotateTo I change it to :

private void RotateTo()
    {
        var distance = Vector3.Distance(capsule.position, curvedLinePoints[rotationIndex].transform.position);
        if(distance < 0.1f)
        {
            rotationIndex++;
        }

        // Determine which direction to rotate towards
        Vector3 targetDirection = curvedLinePoints[rotationIndex].transform.position -capsule.position;

        // The step size is equal to speed times frame time.
        float singleStep = rotationSpeed * Time.deltaTime;

        // Rotate the forward vector towards the target direction by one step
        Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);

        // Draw a ray pointing at our target in
        Debug.DrawRay(capsule.position, newDirection, Color.red);

        // Calculate a rotation a step closer to the target and applies rotation to this object
        capsule.rotation = Quaternion.LookRotation(newDirection);
    }

Two problems :

  1. Even if I set the rotationSpeed to 30 it's still rotating kind of slow. Why 30 is so slow ?

  2. The rotation is on all the axis like in this screenshot but I want it to rotate only on the Y but because to make the capsule stand I have to set the X to -90 when rotating on the Y it's changing the capsule-like scaling it. I want the capsule to like spin around itself.

Rotation

This is how the capsule looks like in the original when running the game before it starts rotating :

Rotation at start

1
Just to be clear, you want to rotate your object in the direction of the current object you are moving to at the same speed? Or want to immediately rotate to the next object in the list curvedLinePoints while moving towards it? - TEEBQNE
@TEEBQNE While moving towards it. but notice that transform is moving towards but I want the capsule to be rotating. The transform is the one that moves the capsule rotating to the next object in the list curvedLinePoints. You got it. - Shitrit Lehava
@TEEBQNE Updated my question with what I did, what are the results, and what I want it to be like. I have two problems. - Shitrit Lehava
Just got back and was able to answer your updated questions. Let me know if you need more information/details or if the second snippet is not working. - TEEBQNE

1 Answers

0
votes

To answer your two newly added questions:

  1. Even if I set the rotationSpeed to 30 it's still rotating kind of slow. Why 30 is so slow?

Your current timestep is set to rotationSpeed * Time.deltaTime. As you mentioned, rotationSpeed is now 30, but what is Time.deltaTime? Time.deltaTime is the amount of seconds between frames, meaning it is 1 / framesPerSecond. Generally framerate is ~60, so for the example we'll call it 1/60 or 0.016666667. When multiplied by your constant of 30, we get 30/60 or 0.5.

The parameter you are using in RotateTowards is maxRadiansDelta. From the wiki, this parameter is:

The maximum angle in radians allowed for this rotation.

As to why your rotation could be defined as slow, is you are moving at roughly 0.5 radians per second. If you increase this value from 30 to something like 60, you then move to 1.0 radians per second and so on.

  1. The rotation is on all the axis like in this screenshot but I want it to rotate only on the Y but because to make the capsule stand I have to set the X to -90 when rotating on the Y it's changing the capsule-like scaling it. I want the capsule to like spin around itself.

The issue here is that RotateTowards will orient your object on all axes to directly take the forward direction and point it at your goal transform. I believe something like this could work?

Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);

newDirection.z = 0f;

capsule.rotation = Quaternion.LookRotation(newDirection, capsule.Up);

I believe that the above snippet should only rotate the object around the Y-axis. Let me know how it goes.