2D Vertical scrolling infinite background

I am trying to use a pool of 3 background sprites, and have them repeat and move back to the top of the stack of objects as they move off camera.

here is what I have so far.
using UnityEngine;
using System.Collections;

public class BackgroundScroller : MonoBehaviour {

	public GameObject background;
	public GameObject[] bgPool = new GameObject[4];
	private float startX = 0;
	private float startY = 5;
	private float startZ = 2;

	// Use this for initialization
	void Awake () 
	{
		for(int i = 0; i < bgPool.Length; i++)
		{
			bgPool *= (GameObject)Instantiate(background);*

_ bgPool*.SetActive(false);_
_
} _
_
}*_

* void Start()*
* {*
* for(int i = 0; i< bgPool.Length; i++)*
* {*
* if(i == 0)*
* {*
_ bgPool*.SetActive(true);
bgPool.transform.position = new Vector3(startX, startY, startZ);
}
else*

* {
bgPool.SetActive(true);
bgPool.transform.position.x = startX;
bgPool.transform.position.z = startZ;*_

* }*
* }*
* }*

* // Update is called once per frame*
* void Update () {*
* if(Input.GetKeyDown(KeyCode.T))*
* {*
* bgPool[0].SetActive(true);*
* bgPool[0].transform.position = new Vector3(0.0f,0.0f,2.0f);*
* Debug.Log(bgPool[1].renderer.bounds);*
* }*
* }*
}
I planned on it starting at Vector3(0,5,2) so that it starts centered, it starts using the bottom of the sprite and not the center of the image, and the Z is set to 2 so that I can add in parallaxing once I get this one to scroll.
right now it creates the pool of objects, which I am using the awake function to do right now, then I was going to use the start function to place the initial objects on the screen, then i would use the update function to check if they were off camera, and if they were it would move them back to the top.
however right now it returns errors and wont place any on screen. I am able to get it to place one object in the right position, but i cant get it to add another one above that one.
the update function was just set because i was seeing what renderer.bounds would return.
and the start function was where I left off when i finally got fed up and came to ask for help

1 Answer

1

I’ve faced something like that and I found two ways to handle it. You can use an gameObject like a barrier to collide with BG elements and reposition it again or you can use the camera view to reposition elements when they are outside the viewport. The method I will use here is about the barrier collision.

First or all you have to put your BG objects inside a parent BG object. I have accomplished it on my hierarchy window like this:

01 - Background

  • bg01
  • bg02
  • bg03
  • bg04
  • bg05

You can put how many objects you want to, I’ve used 5, maybe you should use more or less, its up to you.

Second you have to make all elements scrolling. Its the easy part, just make a script to move the parent BG object and all objects inside will move as well.

Attach your move script or my own snippet on your parent BG:

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

public class MoveBackground : MonoBehaviour {

    public float speed = 2f;
    public float horizontalDirection = -1; //move from right to left
  
	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	    //move the root BG from right to left
        transform.Translate(new Vector3(speed * horizontalDirection * Time.deltaTime, 0, 0));
	}

}

You should change the speed variable to fit your project.

Third part is the funniest one. When the first BG object pass though our invisible barrier, the OnTriggerExit2D will raise up and now the code to change the BG position to make the illusion of an infinite scrolling background will raise up. So the first BG will pass to the last position, the second BG will be the first and so on. We can accomplish it using a game object to trigger the collision (I used a sprite). Make sure this object is the same Z position as the BG objects and it must be positioned outside the camera viewport to the left side.

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


public class BarrierCheck : MonoBehaviour
{

    public Transform rootBG;
    private List<Transform> bgList;

    void Awake()
    {
        bgList = new List<Transform>();

        //get all BGs from the parent BG and put those on the list
        for (var i = 0; i < rootBG.childCount; i++)
        {
            bgList.Add(rootBG.GetChild(i));
        }

        //ordem them all (left to right)
        bgList = bgList.OrderBy(t => t.position.x).ToList();
    }

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    void OnTriggerExit2D(Collider2D c)
    {
        //when the first BG on the list exit the barrier trigger, this snippet is called
        Transform firstBG = bgList.FirstOrDefault();
        Transform lastBG = bgList.LastOrDefault();

        firstBG.Translate(
            new Vector3(lastBG.transform.position.x + firstBG.renderer.bounds.size.x, 0, firstBG.transform.position.z));

        bgList.Remove(firstBG);
        bgList.Add(firstBG);
    }

}

Now we have to attach the parent BG on rootBG to get the children elements. OnTriggerExit2D will be called when some BG object exit the barrier bounds. Make sure all BG objects and barrir object have a Box Collider 2D and Rigidbody 2D with Gravity Scale property to 0.

If you make this it will work.

Sorry about my english I hope it’s clear enough.

I've found a minor bug on the second script. Change the last of firstBG.Translate(); to: firstBG.transform.position = new Vector3(position, firstBG.transform.position.y, firstBG.transform.position.z);