//compares the current vertices timing and y cordinate to the vertices before and after it to see if its "out of bounds"
    private void yClamper(out float clampedY, out float clampedTiming)
    {
        float siblingY;
        float siblingTiming;

        //get the vertex physically higher than the one currently being examined
        currentVertexManager.getHigherVertex(out siblingY, out siblingTiming);

        int controllersTiming = (int)currentVertexManager.getVertexTiming();

        //if statement to check whether the parent of the vertex is the controller:
        if (currentVertexManager.gameObject.transform.parent.transform == gameObject.transform)
        {
            controllersTiming = GridManager.getClosestTiming(currentVertexManager.gameObject.transform.parent.transform.position.y);
        }

        clampedTiming = Mathf.Max(currentVertexManager.getVertexTiming(), siblingTiming);
        clampedY      = GridManager.getYFromTiming((int)clampedTiming);   //====

        currentVertexManager.getLowerVertex(out siblingY, out siblingTiming);

        clampedTiming = Mathf.Min(clampedTiming, siblingTiming);
        clampedY      = GridManager.getYFromTiming((int)clampedTiming);

        if (clampedTiming >= GridManager.getYSegments() - 1)
        {
            Debug.LogWarning("Vertex is going below valid timings");
            clampedTiming = GridManager.getYSegments() - 1;
            clampedY      = GridManager.getYFromTiming((int)clampedTiming);
        }
    }
    //Method used to add a new line renderer vertex and a new vertex sphere.
    public GameObject addVertex(Vector3 pos, int vertexID, GameObject selectedVertex)
    {
        pos = rotateVertex(pos, -getLocalRotation());

        //Get the vertex spheres that are children of this object
        List <GameObject> children = getChildrenVertices();

        //Add the selected vertex to that list (as it won't be a child of the object if it's selected), and sort the list.
        if (selectedVertex)
        {
            children.Add(selectedVertex);
        }

        children.Sort(sortByVertexID);


        //for loop to go through each vertex and update it's vertexID if it's PAST the selected vertex
        foreach (GameObject child in children)
        {
            VertexManager childsVM = child.GetComponent <VertexManager>();
            if (childsVM.getVertexID() >= vertexID)
            {
                childsVM.setVertexID(childsVM.getVertexID() + 1);
            }
        }

        //create a new vertex sphere
        GameObject    newVert    = drawVert(pos, vertexID, false);
        VertexManager newVertsVM = newVert.GetComponent <VertexManager>();

        //make the new vertex's size and "length" field equal to the one currently selected
        if (selectedVertex)
        {
            newVert.transform.localScale = selectedVertex.transform.lossyScale;
            newVertsVM.setVertexLength(selectedVertex.GetComponent <VertexManager>().getVertexLength());
        }
        //add this new vertex to the dictionary of vertexmanagers with its current timing
        timingDict[newVertsVM.getVertexTiming()].Add(newVertsVM);
        //add this new vertex to the list of children, and sort the list again.
        children.Add(newVert);
        children.Sort(sortByVertexID);
        //create a Vector3[] to hold the positions that the line renderer will be set to.
        Vector3[] finalPositions = new Vector3[children.Count];
        //translate the position of every child and add it to finalPositions.
        for (int i = 0; i < children.Count; i++)
        {
            Vector3 tempPos = children[i].transform.position;
            tempPos = rotateVertex(tempPos, -getLocalRotation());
            //tempPos = vertexRotationTwo(tempPos, localRotation+270, i);
            finalPositions[i] = tempPos;
        }

        //create a new vertex on the line renderer and set it's positions to finalPositions.
        attachedLR.positionCount += 1;
        attachedLR.SetPositions(finalPositions);

        boxColliderManager.addBoxCollider(vertexID);

        return(newVert);
    }
    //simple method for changing a hovered over vertices timing and y cordindate
    public void moveVertexDown()
    {
        GameObject nearestVertex = hoverOverVertex();

        if (nearestVertex)
        {
            VertexManager nearestVertexManager = nearestVertex.GetComponent <VertexManager>();
            float         nearestVertexTiming  = nearestVertexManager.getVertexTiming();

            float lowerSiblingY;
            float lowerSiblingTiming;
            nearestVertexManager.getLowerVertex(out lowerSiblingY, out lowerSiblingTiming);

            if (nearestVertexTiming <= GridManager.getYSegments() - 1 && nearestVertexTiming < lowerSiblingTiming)
            {
                Vector3 currentPos = nearestVertex.transform.position;
                Vector3 newPos     = new Vector3(currentPos.x, GridManager.getYFromTiming((int)nearestVertexTiming + 1), currentPos.z);
                nearestVertexManager.moveTo(newPos);
            }
        }
    }
    //simple method for changing a hovered over vertices timing and y cordindate
    public void moveVertexUp()
    {
        GameObject nearestVertex = hoverOverVertex();

        if (nearestVertex)
        {
            VertexManager nearestVertexManager = nearestVertex.GetComponent <VertexManager>();
            float         nearestVertexTiming  = nearestVertexManager.getVertexTiming();

            float higherSiblingY;
            float higherSiblingTiming;
            nearestVertexManager.getHigherVertex(out higherSiblingY, out higherSiblingTiming);

            if (nearestVertexTiming != 0 && nearestVertexTiming > higherSiblingTiming)
            {
                Vector3 currentPos = nearestVertex.transform.position;
                Vector3 newPos     = new Vector3(currentPos.x, GridManager.getYFromTiming((int)nearestVertexTiming - 1), currentPos.z);
                nearestVertexManager.moveTo(newPos);
            }
        }
    }
    //method called by pulse manager to calculate a pulse should be on this line renderer. (and for creating new lead on pulses)
    public Vector3 interpole(float height, bool playVertex)
    {
        float lowerBoundTiming = float.MinValue;
        float upperBoundTiming = float.MaxValue;
        int   lowerBoundIndex  = 0;
        int   upperBoundIndex  = 0;
        int   flooredHeight    = Mathf.FloorToInt(height);

        //get all of the children, even ones attached to controllers.
        List <GameObject> childrenVertices = getAllChildrenVerticesForInterpole();

        childrenVertices.Sort(sortByVertexID);
        //first 1/3 of method used for deducing which 2 vertices the pulse should be between based on a given height.

        foreach (GameObject Vertex in childrenVertices)
        {
            VertexManager currentVertexManager = Vertex.GetComponent <VertexManager>();
            if (currentVertexManager.getVertexTiming() >= lowerBoundTiming && currentVertexManager.getVertexTiming() <= height)
            {
                lowerBoundTiming = currentVertexManager.getVertexTiming();
                lowerBoundIndex  = currentVertexManager.getVertexID();
            }
            if (currentVertexManager.getVertexTiming() < upperBoundTiming && currentVertexManager.getVertexTiming() > height && currentVertexManager.getVertexTiming() != upperBoundTiming)
            {
                upperBoundTiming = currentVertexManager.getVertexTiming();
                upperBoundIndex  = currentVertexManager.getVertexID();
            }
        }

        if (lastHeight > flooredHeight && flooredHeight == 0)
        {
            if (playVertex)
            {
                foreach (VertexManager vm in timingDict[0])
                {
                    vm.playVertex();
                }
            }
        }
        else if (lastHeight < flooredHeight)
        {
            float diffOfHeights = flooredHeight - lastHeight;
            if (playVertex && flooredHeight < GridManager.getYSegments() - 1)
            {
                foreach (VertexManager vm in timingDict[flooredHeight])
                {
                    vm.playVertex();
                }
            }
        }

        if (flooredHeight != -1)
        {
            lastHeight = flooredHeight;
        }

        float difference   = upperBoundTiming - lowerBoundTiming;
        float segment      = 1 / difference;
        float leftover     = height - lowerBoundTiming;
        int   numberOfDivs = Mathf.FloorToInt(leftover);
        float t            = (numberOfDivs * segment) + ((leftover % 1) / difference);

        if (flooredHeight == -1)
        {
            //lead on pulse:
            return(Vector3.Lerp(PulseTranslation(attachedLR.GetPosition(0)), PulseTranslation(attachedLR.GetPosition(1)), 1 - (height * -1)));
        }
        else
        {
            return(Vector3.Lerp(PulseTranslation(attachedLR.GetPosition(lowerBoundIndex)), PulseTranslation(attachedLR.GetPosition(upperBoundIndex)), t));
        }
    }