Search Unity

Scrolling Background 2D (Sprite Background)

Discussion in '2D' started by abelreyes, Feb 25, 2015.

  1. abelreyes

    abelreyes

    Joined:
    Sep 11, 2013
    Posts:
    28
    Good Morning!
    I'm Abel, working with a little team in a 2D game for Android. Our game try to be really cheap in terms of cpu/gpu.

    In order to made a infinite background, i've made two gameobjects inside of canvas render of new Unity UI (To easily fill the screen), and made them fall together unitl each one arrives to the end of the camera, then its moved to the begining of the screen space, and this loops forever.

    UnityBackground.png

    Basically it is what you can see on the image... Sky1 - Sky2 are the two parts of the whole image, and them scroll down until the top part of each, arrives to the top image bottom position of the bottom background. (Don't know if it's clear...). Well, basically what i said at the begining...

    This has two important problems:
    -First: It is too lagged... It doesn't seem to lag the whole game, but the way it scrolls seems really lagged.
    -Second: At the moment of the repositione, maybe becouse of a small delay during Update function, it creates a small line between the two background pices, and with some of our backgrounds it looks horrible...

    I've seen also this tutorial:

    https://unity3d.com/es/learn/tutori...ive-training-archive/2d-scrolling-backgrounds

    But this tutorial does it with 3D components, and our small sprites (that are scalled on unity) gets blured, and also I'm not sure if using 3D elements will be good for the game performance...

    Here there is the code that scroll the backgrounds, it's attached to sky2 (Not important, i selected it randomly...):

    Code (JavaScript):
    1.  
    2. var speed : int;
    3.  
    4. var mainCamera : Camera;
    5.  
    6. var skyOne : UI.Image;
    7. var skyTwo : UI.Image;
    8.  
    9. function Start () {
    10.     mainCamera = Camera.main;
    11.     skyTwo.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0.5,1.5, 1));
    12.     skyOne.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0.5, 0.5, 1));
    13.     topPosition = skyTwo.transform.position;
    14.     bottomPosition = Camera.main.ViewportToWorldPoint(Vector2(0, -0.5));
    15. }
    16.  
    17. function FixedUpdate () {
    18.     skyOne.transform.Translate(Vector2(0, 10 * -1 * Time.deltaTime * speed/10));
    19.     skyTwo.transform.Translate(Vector2(0, 10 * -1 * Time.deltaTime * speed/10));
    20.  
    21.     if(skyOne.transform.position.y <= bottomPosition.y + offsetCorrector){
    22.         offsetCorrector+=0.1;
    23.         skyOne.transform.position = topPosition;
    24.     }
    25.     if(skyTwo.transform.position.y <= bottomPosition.y + offsetCorrector){
    26.         offsetCorrector+=0.1;
    27.         skyTwo.transform.position = topPosition;
    28.     }
    29. }
    The var offsetCorrector was created to corrent the line between both backgrounds... i don't like it but it was the only solution i found...
    Anyone know a better way for doing that or what i've made wrong?

    Thanks to everyone!!
    Abel!
     
    SavaliyaNiraj likes this.
  2. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    Typically for the gameplay elements you would use sprites, and the UI elements for the UI, but if it works it works!

    To fix the lines between your objects, you need to take into account that the object will not land directly on the bottom position.
    Code (csharp):
    1. if (skyOne.transform.position.y <= bottomPosition.y) {
    2.     var offset : float = skyOne.transform.position.y-bottomPosition.y;
    3.     skyOne.transform.position = topPosition+Vector3.up*offset;
    4. }
    To fix the lagginess you will want to use Update rather than FixedUpdate.
     
    abelreyes likes this.
  3. PGJ

    PGJ

    Joined:
    Jan 21, 2014
    Posts:
    899
    You could also use quad with a scrolling texture on it. Set the texture to "Wrap Mode" to repeat and add a script similar to this:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Parallax : MonoBehaviour
    5. {
    6.         public float speed = 0.5f;
    7.         public float start = 0;
    8.  
    9.         Vector2 offset = new Vector2 (0, 0);
    10.    
    11.         void Update ()
    12.         {
    13.                 offset.x = start + Time.time * speed;
    14.        
    15.                 renderer.material.mainTextureOffset = offset;
    16.         }
    17. }
    18.  
     
    theANMATOR2b and abelreyes like this.
  4. abelreyes

    abelreyes

    Joined:
    Sep 11, 2013
    Posts:
    28
    It corrects (more or less) the offset (sometimes appears the withe line i mentioned as a "flash"), but the lag effect stills there... Would i obtain better performance using normal sprites with transform instead of rect transform and UI image?

    In that case, how could i get to fit the sprite image to camera size?

    Thanks Daniel!
    Abel!
     
  5. abelreyes

    abelreyes

    Joined:
    Sep 11, 2013
    Posts:
    28
    I tryied this, as it's what the tutorial i mentionet sais, buy as i'm using pixel sprites and I import them using Point filter mode, but when I set it as a texture in order to change wrap mode, the sprite gets blured and also when aplying the offset to the texture, when it ends the real size of the sprite, starts showing a extrange ratio aspect, seems like unity try to elongate it...

    Thanks!!
    Abel!
     
  6. PGJ

    PGJ

    Joined:
    Jan 21, 2014
    Posts:
    899
    That sound really weird. I've done projects that uses more or less the same stuff and it works great. If you go to:
    http://gnulix.org/unity/runnertest.7z
    You'll find a little, test project I did with my students. It uses offsets for the parallax scroll. Have a look at it, it might help you...
     
  7. abelreyes

    abelreyes

    Joined:
    Sep 11, 2013
    Posts:
    28
    I've been looking your project a while, and I see what you say...
    Buy my problem is that i'm using really low resulution pixel images (120x214), and if I import it as a texture, it gets blured... When I was using sprite render instead, on the importer i selected Point at Filter Mode, and that made images look ok, but if I select the same option using texture instead, the image shows blured as I said.

    Using Texture Type: Sprite
    Filter Mode: Point
    Sprite-0002.png
    Using Texture Type: Sprite
    Filter Mode: Point
    Sprite-0003.png

    EDIT: Also, can I ask how i can do to scale the gameobject that contains the texture to fit horizontally the camera size? I see some solutions on other posts but I can't manage to make it work on my project...

    Thanks for all the help!
    Abel!
     
    Last edited: Feb 26, 2015
  8. PGJ

    PGJ

    Joined:
    Jan 21, 2014
    Posts:
    899
    Have you tried setting "Texture Type" to Advanced? You get a lot more parameters. Try setting "Non Power of 2" to None, "Filter Mode" point and Format to "Automatic Truecolor" (there are several options here that might be worth exploring). "Bypass sRGB Sampling" might be worth checking out as well (didn't see any difference in my case). I made a super lowres texture and imported it with these settings. It is super crisp, no matter how I scale the quad.

    Something like this should scale the quad to fit the width of the screen.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Scaler : MonoBehaviour
    6. {
    7.  
    8.  // Use this for initialization
    9.  void Start()
    10.  {
    11.  float cameraWidth =
    12.  Mathf.Abs(Camera.main.ViewportToWorldPoint(Vector3.one).x - Camera.main.ViewportToWorldPoint(Vector3.zero).x);
    13.  float size = cameraWidth / (renderer.bounds.size.x / transform.localScale.x);
    14.  transform.localScale = new Vector3(size, size, 1);
    15.  }
    16. }
    17.  
    18.  
     
    abelreyes likes this.
  9. abelreyes

    abelreyes

    Joined:
    Sep 11, 2013
    Posts:
    28
    Thanks again!

    Okey, now I have the texture correctly scaled and is showing like the first image, but I found that when I compile and run on my mobile the texture doesn't reapeat as it shoud... I found a message on unity Inspector while importing that says "Graphics device doesn't support Repeat wrap mode on NPOT textures. Falling back to Clamp"... That means that I should have to redimensione my textures to fit the width and the height of them to a power of 2, or there is another way?

    Thanks so much! Abel!
     
  10. PGJ

    PGJ

    Joined:
    Jan 21, 2014
    Posts:
    899
    Yes, unfortunately some devices require POT textures. Although there might be ways to get around this, I think the easiest and best bet is to make it a POT texture.
     
    abelreyes likes this.
  11. abelreyes

    abelreyes

    Joined:
    Sep 11, 2013
    Posts:
    28
    Okey, no problem! I scaled the image and now i works fine!

    So, here I close the thread, and thanks so much!
    Abel!