Пытаюсь зациклить фон игры, при попытке перенести положение объекта слева направо багается

При старте скрипта, я List заполняю детьми объекта к которому был прикреплен скрипт, после в методе Update пытаюсь узнать ушел ли 1 элемент налево за камеру, после проверяю отрисовывается ли он, после чего я получаю последний элемент списка, узнаю его место положение и передаю 1 элементу который уже вышел налево за камеру, местоположение последнего элемента в сцене, что бы он появился за ним, после чего удаляю 1 элемент и добавляю его в конец списка. Но все не получается, может есть другой метод зацикливания фона, помогите пожалуйста

[![][1]

public class LoopBackGround : MonoBehaviour
{
    public Vector2 speed = new Vector2 (10, 10);
    public Vector2 direction = new Vector2 (-1, 0);
    private List<Transform> backgroundPart; // все дети которые пренадлежат элементe на который присоединил скрипт
    public bool isLooping = false;
    public bool isCamera = false;
    private int steps = 0;

    private void Start()
    {
        if (isLooping) // надо ли элемент зациклить
        {
            backgroundPart = new List<Transform>(); // инициализирую List

            for (int i = 0; i < gameObject.transform.childCount; i++)
            {
                Transform child = transform.GetChild(i);// получая ребенка элемента

                if (child.GetComponent<Renderer>() != null) // узнаю есть ли у него компонент рендера
                {
                    backgroundPart.Add(child);// добавляю в List
                }
            }
            backgroundPart = backgroundPart.OrderBy(t => t.position.x).ToList();
        }
    }

    private void Update()
    {
        Vector3 move = new Vector3(speed.x * direction.x, speed.y * direction.y, 0); // задаю движение элементу
        move *= Time.deltaTime; // Умножаю ее на скорость отрисовки кадра
        transform.Translate(move); // Передвигаю элемент

        if (isCamera) // Это камера ?
            Camera.main.transform.Translate(move);  // Если да то двигаю камеру

        if (isLooping) // Элемент надо зациклить ?
        {
            /*Vector3 cam = Camera.main.transform.position;*/ // Узнаю координаты камеры
            Transform firstChild = backgroundPart.FirstOrDefault(); // получаю 1 элемент
            if (firstChild != null) // узнаю не пустой ли 1 элемент
            {
                for (int i = 0; i < backgroundPart.Count; i++)
                {
                    if ((firstChild.position.x + 20) < Camera.main.transform.position.x) // проверяю ушел ли объект налево
                    {

                        if (firstChild.GetComponent<Renderer>().isVisible == false)
                        {
                            print(firstChild.gameObject.name);
                            Transform lastChild = backgroundPart.LastOrDefault(); // получаю последний объект List
                            print(lastChild.gameObject.name);
                            firstChild.transform.Translate(new Vector3(lastChild.position.x, lastChild.position.y, lastChild.position.z)); // получаю место нахождение последнего элемента и передаю его первому
                            backgroundPart.Add(firstChild); // добавляю в List первый элемент
                            backgroundPart.Remove(firstChild); // удаляю первый элемент что бы двигать список справо налево

                            //print(backgroundPart[i].gameObject.name);
                            //lastElem = new Vector3(gameObjects.LastOrDefault().transform.position.x + 40, 0, 0);
                            //Transform first = gameObjects.FirstOrDefault(); // передаю элемент который ушел налево

                         //gameObjects[i].transform.Translate(lastElem); // Переношу элемент направо
                            //gameObjects.Add(first); // Добавляю первый элемент в конец
                            //gameObjects.Remove(first); // Удаляю первый элемент

                        //Transform lastChild = backgroundPart.LastOrDefault();
                        //Vector3 lastPosition = new Vector3(lastChild.transform.position.x, lastChild.transform.position.y, lastChild.transform.position.z);
                        //Vector3 lastSize = (lastChild.GetComponent<Renderer>().bounds.max - lastChild.GetComponent<Renderer>().bounds.min);

                        //firstChild.position = new Vector3(lastPosition.x + lastSize.x, firstChild.position.y, firstChild.position.z);
                        //backgroundPart.Remove(firstChild);
                        //backgroundPart.Add(firstChild);
                        }
                    }
                }
            }
        }
        steps++;
        print($"{steps}) Проверка порядка элементов!");
        for (int i = 0; i < backgroundPart.Count; i++)
        {
            print(backgroundPart[i].gameObject.name);
        }
        // СПИСОК НЕ ОБНОВЛЯЕТСЯ, 1 ЭЛЕМЕНТ ПЕРЕНОСИТСЯ В КОНЕЦ ОСТАЛЬНЫЕ НЕ ПЕРЕНОСЯТСЯ
    }
}

Ответы (2 шт):

Автор решения: Yaroslav
Transform firstChild = backgroundPart.FirstOrDefault(); // получаю 1 элемент
// - Берёте первый элемент из List
...
backgroundPart.Add(firstChild); // добавляю в List первый элемент
// - Добавляю в List ранее взятый элемент (который тау уже есть)
backgroundPart.Remove(firstChild); // удаляю первый элемент что бы двигать список справо налево
// - Удаляете только что добавленный элемент

Звоните 03!

transform.Translate(move); // Передвигаю элемент
// - Какой элемент? Это корневой GameObject
if (isCamera) // Это камера ?
    Camera.main.transform.Translate(move); // Если да то двигаю камеру
// - Одно другому не мешает?

Если isLooping false с тем-же успехом можно тупо отключить скрипт.

isCamera ? Что тут забыла камера? Скрипт не о её поведении! И опять же, с тем же успехом...

public class CameraMovement : MonoBehaviour {
    public float Speed = 10f;
    public Vector2 Direction = new Vector2 (-1, 0);

    private void Update () {
        Camera.main.transform.Translate(Direction*Speed*Time.deltaTime); // Да так можно! Vector2*float
    }
}

public class LoopBackGround : MonoBehaviour {
    public List<Transform> _elements;
    private float _elementWidth = 20; // Ширина элемента
    private float _halfFrameWidth; // Полавина ширина камеры

    private void Start () {
        _halfFrameWidth = 20; // Не помню как определять, как нибудь сам...
        _elements = new List<Transform>();
        for (int i = 0; i < gameObject.transform.childCount; i++) {
            Transform child = transform.GetChild(i);
            if (child.GetComponent<Renderer>() != null)
                _elements.Add(child);
        }
        _elements = _elements.OrderBy(t => t.position.x);
    }

    private void Update () {
        Vector2 CameraPosition = Camera.main.transform.position;
        int Count = _elements.Count;
        int TotalElements = Mathf.FloorToInt((CameraPosition.x-_halfFrameWidth)/_elementWidth); // Сколько элементов от x0 до левой части камеры
        for (int i = 0; i < Count; i++) { // Выстраиваем элементы под катр
            int ElementNum = TotalElements+i; // Номер элемента i от х0
            int NumOnList = ElementNum%Count; // Номер элемента в кадре (% - остаток от деления)
            if (NumOnList < 0)
                NumOnList += Count;
            _elements[NumOnList].localPosition = new Vector3(ElementNum*_elementWidth, CameraPosition.y, 0);
        }
    }
}
→ Ссылка
Автор решения: danil2283376

Решил сам, критику человека понял, использую движение для камеры в отдельном скрипте. По итогу решил сам справиться с задачей. Спасибо за помощь !

Вот код :

     `
public class Loop : MonoBehaviour
{
    public Vector2 speed = new Vector2(10, 10);
    public Vector2 direction = new Vector2(-1, 0);
    public bool isLooping = false;

    private List<Transform> backgroundPart;

    private void Start()
    {
        // Корневую пустышку нужно зациклить?
        if (isLooping)
        {
            // инициализирую список
            backgroundPart = new List<Transform>();
            for (int i = 0; i < transform.childCount; i++)
            {
                // получаю ребенка у корневого объекта
                Transform child = transform.GetChild(i);
                // проверяю есть ли у него объект рендерера
                if (child.GetComponent<Renderer>() != null)
                    backgroundPart.Add(child);
            }
            // выполняю сортировку по x кто левее тот первый в списке
            backgroundPart = backgroundPart.OrderBy(t => t.position.x).ToList();
        }
    }

    private void Update()
    {
        Vector3 move = new Vector3(speed.x * direction.x, speed.y * direction.y, 0); // движение корневого объекта
        move *= Time.deltaTime; // движение умножаю на скорость отрисовки кадра
        transform.Translate(move); // задаю движение корневому объекту

        if (isLooping) // корневой объект зацикленный
        {
            // узнаю координаты камеры
            Vector3 pointCamera = Camera.main.transform.position;
            // получаю последний объекта списка
            Transform firstChild = backgroundPart.FirstOrDefault();
            // проверяю есть ли ссылка на объект
            if (firstChild != null)
            {
                // Проверяю ушел ли объект налево
                if ((pointCamera.x - 20) > firstChild.transform.position.x)
                {
                    // получаю последний объект списка
                    Transform lastChild = backgroundPart.LastOrDefault();
                    // вычитаю из последнего расстояние по x до первого элемента
                    Vector2 distance = new Vector2(lastChild.position.x - firstChild.position.x, 0);
                    // Vector3 с дефолтными значениями
                    Vector3 bias = default;
                    // узнаю объект является ли платформой
                    if (transform.gameObject.tag == "Platform")
                    {
                        // передаю значения
                        bias = new Vector3(firstChild.position.x + 50, Random.Range(-5, 5));
                        // двигаю элементы
                        firstChild.position = bias;
                    }
                    else if (transform.gameObject.tag == "Background")
                    {
                        bias = new Vector3(distance.x + 20, firstChild.transform.position.y, firstChild.position.z);
                        firstChild.transform.Translate(bias);
                    }
                    // удаляю найденный объект
                    backgroundPart.Remove(firstChild);
                    // добавляю нужный объект в конец списка
                    backgroundPart.Add(firstChild);
                }
            }
        }
    }
}`
→ Ссылка