- Home /
How do I make a 2D scrolling background with variable speed?
Hello,
I've got a working 2D scrolling background, using the following code:
public class Background : MonoBehaviour
{
public bool CanScroll { get; set; }
public float Speed
{
get { return _speed; }
set { _speed = value; }
}
public float StartingSpeed
{
get { return _startingSpeed; }
}
[SerializeField] private float _startingSpeed = 0.1F;
private Renderer _renderer;
private float _speed;
protected void Awake()
{
_renderer = GetComponent<Renderer>();
CanScroll = true;
_speed = _startingSpeed;
}
protected void Update()
{
if (!CanScroll) return;
// Pretend to be endlessly scrolling
float y = Mathf.Repeat(Time.time * _speed, 1);
Vector2 offset = new Vector2(0, -y);
_renderer.sharedMaterial.SetTextureOffset("_MainTex", offset);
}
}
However, I want to be able to adjust _speed at runtime, and have it still scroll smoothly (or at least fake scrolling smoothly).
Currently when I adjust _speed at runtime, the background image will jump position very obviously, before switching to the new scrolling speed. And when I increase _speed in an Update loop, the background will suddenly scroll very quickly, when accelerating, then become slower when _speed stops increasing (that means when _speed is 15, it will be scrolling slower than when _speed is increasing, but at say 14.2, which doesn't make sense to me).
Ideally, I want to be able to increase and decrease _speed from another script's Update loop (through the Speed property) and have the background accelerate and decelerate smoothly.
Thanks for reading. Let me know if you need more information.
Answer by timohausmann · Jul 13, 2015 at 01:22 AM
Here are some suggestions and an example that changes speed every 2 seconds with easing the speed.
don't use Time.time to multiply your speed. When you change speed, you will get unpredictable position jumpings. Check out Time.deltaTime to be framerate independent.
store the actual speed, the desired speed and the texture position as seperate variables to get more control.
I'm unsure about your double private/publics and the custom get/set methods. I will leave it out in this example.
public class Background : MonoBehaviour {
public bool CanScroll;
private Renderer _renderer;
public float _speed = 0.1f; //current scrolling speed
private float _desiredSpeed; //desired scrolling speed
private float _pos; //total texture offset
private float _lastChange; //just for demonstration
protected void Awake()
{
_renderer = GetComponent<Renderer>();
CanScroll = true;
_desiredSpeed = _speed;
_lastChange = 0; //just for demonstration
}
protected void Update()
{
if (!CanScroll) return;
//just for demonstration: change desired speed
if (Time.time > _lastChange + 2) {
_desiredSpeed = Random.Range(-2f, 2f);
_lastChange = Time.time;
Debug.Log ("Set Speed To " + _desiredSpeed);
}
//this is where the magic happens: easing by hand!
//Play with the value 0.01f to speed up or slow down the easing.
_speed += (_desiredSpeed - _speed) * 0.01f;
//add current speed to the position
_pos += _speed * Time.deltaTime;
//for me it works without Mathf.Repeat
//float y = Mathf.Repeat(_pos, 1);
Vector2 offset = new Vector2(0, _pos);
_renderer.sharedMaterial.SetTextureOffset("_MainTex", offset);
}
}
Hope this helps!
Homeboy didn't say thanks, so I'll thank you for him. But you the real $$anonymous$$VP timohausmann!
Thank you very much i had the same problem and this helped so much. The code is easy to use and understand.
Your answer

Follow this Question
Related Questions
parallax scrolling background 2 Answers
Vertical camera scrolling fix? 0 Answers
Resolution Independent Scrolling Background 0 Answers
Perspective scrolling background 1 Answer