void Update()
    {
        if (isActive == false)
        {
            return;
        }

        currentSpeed += Time.deltaTime / generatorConfig.pipeSpeedChangeDurationSec;

        for (int i = livePipeSegments.Count - 1; i >= 0; i--)
        {
            PipeSegment pipeSegment = livePipeSegments[i];
            if (pipeSegment.transform.localPosition.z <= generatorConfig.pipeDisappearZ)
            {
                livePipeSegments.RemoveAt(i);
                SimplePool.Despawn(pipeSegment.gameObject);
            }
        }

        while (livePipeSegments.Count < generatorConfig.maxAlivePipes)
        {
            bool        firstPipe = livePipeSegments.Count == 0;
            PipeSegment selectedPipePrefab;
            bool        inBetweenEmptyPipe = firstPipe || livePipeSegments[livePipeSegments.Count - 1].HasObstacles;
            if (pipeNumber <= generatorConfig.startEmptyPipes || inBetweenEmptyPipe)
            {
                selectedPipePrefab = generatorConfig.emptyPipe;
            }
            else
            {
                selectedPipePrefab = generatorConfig.pipes[Random.Range(0, generatorConfig.pipes.Length)];
            }

            GameObject  newPipe        = SimplePool.Spawn(selectedPipePrefab.gameObject, Vector3.zero, Quaternion.identity, pipeHolder);
            PipeSegment newPipeSegment = newPipe.GetComponent <PipeSegment>();
            livePipeSegments.Add(newPipeSegment);
            if (firstPipe)
            {
                newPipe.transform.position = new Vector3(0, 0, generatorConfig.pipeDisappearZ);
            }

            //INIT THE PIPE
            newPipeSegment.Init();
            newPipe.transform.localRotation = Quaternion.Euler(0, 0, newPipeSegment.StartRotationZ);
            pipeNumber++;
        }

        Vector3 firstPipePosition = Vector3.zero;

        for (int i = 0; i < livePipeSegments.Count; i++)
        {
            PipeSegment pipeSegment = livePipeSegments[i];

            if (pipeSegment.ObstaclesVisible == false && i <= generatorConfig.obstaclesApperPipeIndex)
            {
                pipeSegment.ShowObstacles();
            }

            if (i == 0)
            {
                float moveDelta = -1 * Time.deltaTime * currentSpeed;
                pipeSegment.transform.localPosition = new Vector3(0, 0, pipeSegment.transform.localPosition.z + moveDelta);
                firstPipePosition = pipeSegment.transform.localPosition;
            }
            else
            {
                pipeSegment.transform.localPosition = firstPipePosition + new Vector3(0, 0, i * pipeSegment.Length);
            }
        }
    }