Notifications
Article
INFINITE SCROLLING OF 2D BACKGROUND IN UNITY3D USING C# (SNAPPING BOUND TO BOUND)
Updated 9 months ago
214
5
INFINITE SCROLLING OF 2D BACKGROUND IN UNITY3D USING C# (SNAPPING BOUND TO BOUND)

Parallax scrolling:

An effect that you find in every single 2D game for 15 years is “Parallax Scrolling“.
To make it short, the idea is to move the background layers at different speeds (i.e., the farther the layer is, the slower it moves). If done correctly, this gives an illusion of depth. It’s a cool, nice and easy-to-do effect.

Idea ???

Adding a scrolling axis need a bit of thinking on how we will make the game with this new aspect.
What do we want to move?

We have a decision to take here :

  1. First choice: The player and the camera move. The rest is fixed.
  2. Second choice: The player and the camera are static. The level is a treadmill.
The first choice is a no-brainier if you have a Perspective camera. The parallax is obvious: background elements have a higher depth. Thus, they are behind and seems to move slower.
But in a standard 2D game in Unity, we use an Orthographic camera. We don’t have depth at render.

About the camera:

Remember the “Projection” property of your camera game object.
Perspective means that the camera is a classic 3D camera, with depth management. Orthographic is a camera that renders everything at the same depth. It’s particularly useful for a GUI or a 2D game.
In order to add the parallax scrolling effect to our game, the solution is to mix both choices. We will have two scrolling:
  1. The player is moving forward along with the camera.
  2. Background elements are moving at different speeds (in addition to the camera movement).
Here is the script for Scrolling background:
using UnityEngine; using System.Linq; using System.Collections.Generic; public class InfiniteScrolling : MonoBehaviour { public float speed; private List<Transform> backgroundPart; void Start() { 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); } } backgroundPart = backgroundPart.OrderBy ( t => t.position.x ) .ToList(); } void Update() { transform.Translate (Vector2.right * Time.deltaTime * speed); Transform firstChild = backgroundPart.FirstOrDefault(); if (firstChild != null) { if (firstChild.position.x < Camera.main.transform.position.x) { if (firstChild.GetComponent<Renderer>().IsVisibleFrom(Camera.main) == false) { Transform lastChild = backgroundPart.LastOrDefault(); Vector3 lastPosition = lastChild.transform.position; 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 ); } } } } }
Explanation of Scripting:
  1. We need a public variable to turn on the “looping” mode in the “Inspector” view.
  2. We also have to use a private variable to store the layer children.
  3. In the Start() method, we set the background-part list with the children that have a renderer. Thanks to a bit of LINQ, we order them by their X position and put the leftmost at the first position of the array.

Sprite Renderer Extension:

We Also need some tweaking in our sprite renderer to check if the sprite is visible or not in camera. and also to calculate its bounds dynamically.
Here is our SpriteRendererExtension Script:
using UnityEngine; public static class SpriteRendererExtension { public static bool IsVisibleFrom(this Renderer renderer, Camera camera) { Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera); return GeometryUtility.TestPlanesAABB(planes, renderer.bounds); } }
Note: We use GeometryUtility for calculating view of our Camera to the sprite.
Courtesy: pixelnest.io, ozappstudio.com

Owais Zahid
Technical Lead - Programmer
3
Comments
Owais Zahid
9 months ago
Technical Lead - Programmer
Mark PoeppelmeierIf you need more tips you can always just Connect with me and chat privately
0
Mark Poeppelmeier
Staff
9 months ago
Product Manager Unity Connect - Producer
If you need more tips you can always just Connect with me and chat privately
1
Owais Zahid
9 months ago
Technical Lead - Programmer
Oh thank you @Mark Poeppelmeier I really appreciated that.
0
Mark Poeppelmeier
Staff
9 months ago
Product Manager Unity Connect - Producer
@Owais Zahid - you know you should be able to use the code snippet editing feature to remove those white lines between your code.
1