Parallax scrolling using orthographic camera

Hi

I am making a 2d game and want multiple layers of parallax (maybe 5 layers).

Whats the best practice, move the player and camera on a static background, or keep the player still and move the background?

I thought maybe it would be a good optimization to do static batching on the background, which means it can’t move, but because I’m using ortho not perspective camera, whats the best way to achieve this? Use a different camera for each parallax layer and have them follow the player camera at different speeds? Would there be any downsides to using this approach on mobile?

Many thanks

Here are two solutions:

  1. Make a perspective camera (just one) and put your layers at different z positions. Then all you have to do is make this camera move when your ortho camera moves. Because it’s a perspective camera the parallax layers will move at different speeds depending on how far they are from the camera. You can use static batching with this method since the layers are not moving in the world, only the camera moves.

  2. Move the layers from script. Each layer should move at a different speed when your ortho camera moves. Here’s what I’ve done:

    [ExecuteInEditMode]
    public class ParallaxBackground : MonoBehaviour
    {
    public ParallaxCamera parallaxCamera;
    List parallaxLayers = new List();

    void Start()
    {
    if (parallaxCamera == null)
    parallaxCamera = Camera.main.GetComponent();

      if (parallaxCamera != null)
        parallaxCamera.onCameraTranslate += Move;
    
      SetLayers();
    

    }

    void SetLayers()
    {
    parallaxLayers.Clear();

      for (int i = 0; i < transform.childCount; i++)
      {
          ParallaxLayer layer = transform.GetChild(i).GetComponent<ParallaxLayer>();
    
          if (layer != null)
          {
              layer.name = "Layer-" + i;
              parallaxLayers.Add(layer);
          }
      }
    }
    
    void Move(float delta)
    {
        foreach (ParallaxLayer layer in parallaxLayers)
      {
          layer.Move(delta);
      }
    

    }
    }

And:

[ExecuteInEditMode]
public class ParallaxLayer : MonoBehaviour
{
      public float parallaxFactor;

      public void Move(float delta)
      {
          Vector3 newPos = transform.localPosition;
          newPos.x -= delta * parallaxFactor;

          transform.localPosition = newPos;
      }

}

[ExecuteInEditMode]
public class ParallaxCamera : MonoBehaviour 
{
    public delegate void ParallaxCameraDelegate(float deltaMovement);
    public ParallaxCameraDelegate onCameraTranslate;

    private float oldPosition;

    void Start()
    {
	    oldPosition = transform.position.x;
    }

    void Update()
    {
	    if (transform.position.x != oldPosition)
	    {
		    if (onCameraTranslate != null)
		    {
			    float delta = oldPosition - transform.position.x;
			    onCameraTranslate(delta);
		    }

		    oldPosition = transform.position.x;
	    }
    }
}

How it works: First you have to have a gameobject with the ParallaxBackground script and add the layers as children to this game object and put the ParallaxLayer script on these.
Then all you have to do is call Move(delta) where delta is the distance that the ortho camera moved. I made an event in the parallax camera, but you can do as you will. The layers will move with parallaxFactor ( if parallaxFactor is 1 then the layer will move at the same speed as the camera, if it’s 0.5 then it will move 2 times slower, 2 for 2 times faster)

I prefer the second method since it’s more 2d ish, but I have used both methods and both work well.

1 Like