- Home /
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[i] = (GameObject)Instantiate(background);
bgPool[i].SetActive(false);
}
}
void Start()
{
for(int i = 0; i< bgPool.Length; i++)
{
if(i == 0)
{
bgPool[i].SetActive(true);
bgPool[i].transform.position = new Vector3(startX, startY, startZ);
}
else
{
bgPool[i].SetActive(true);
bgPool[i].transform.position.x = startX;
bgPool[i].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
Answer by Dunkelheit · Dec 10, 2013 at 03:50 PM
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 $$anonymous$$or 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);
I had done this slightly different, It took forever for unity to approve my question and I figured it out while I was fiddling with it.
The way I did it is I started off with 5 objects like you did. However I created an empty game object that holds the script to populate the background for the start.
It takes a game object as a variable (One of the background tiles), then it copies that into an array, I eventually was able to drop the array down to 2 tiles and it not lose continuity. After it creates the array it positions then on the screen the way they need to be setup.
Then on the background tiles themselves I added a function to move the tiles downwards to create the illusion that the player is moving through the environment. Then I had the background tile trigger a bool vaule to true when Renderer.IsVisible. If that is set to true and it triggers OnBecameInvisible, it resets the position of the tile to the top of the "chain".
I can post some scripts if you would like to see more.
Your answer
Follow this Question
Related Questions
2D Infinite Vertical Background scrolling 0 Answers
Reverse animation loop stops at frame zero 0 Answers
There is a generation lag 1 Answer
2D Animation does not start 1 Answer
Falling Bomb Script Not Working Right 0 Answers