- Home /
How to slow down a scrolling object?
I'm using a script to scroll a background. It doesn't have a Rigidbody as it's a tiled object. What I'd like to do is to slow down the scrolling background (gradually if possible). Please see the script below so far. The good thing is it technically works, but it suddenly cuts down its speed drastically and this makes it look really "Choppy".
EDIT: code/'ll explain a little better. When player hits powerup - I wanted him to have everything slow down, except for the player. At this point, everything works great except for the scrolling background. It does slow down like a charm, but the problem is as soon as player hits that trigger the background resets immediately on that frame, and it just looks bad. If you blink you can miss that, but high chances are that your eyes are glued to that particular moment. I'd like for it to very quickly slow down, but not just "Jump" or reset back to it's original position. EDIT2: Notified followers.
using UnityEngine;
using System.Collections;
public class BGScroller : MonoBehaviour
{
public float scrollSpeed;
public float halfScrollSpeed;
public float tileSize;
PlayerMovement script;
Vector2 startPosition;
Vector2 newPosition;
// Use this for initialization
void Start()
{
script = GameObject.Find("Player").GetComponent<PlayerMovement>();
startPosition = transform.position;
}
// Update is called once per frame
void FixedUpdate()
{
if (!script.scrollerThing) //If power up NOT activated scroll at regular speed.
{
float floatNewPosition = Mathf.Repeat(Time.time * scrollSpeed, tileSize);
newPosition = new Vector2(-floatNewPosition, 0f);
transform.position = startPosition + newPosition;
}
else //Power up activated resulting in half speed of scrolling.
{
halfScrollSpeed = scrollSpeed / 2;
float floatNewPosition = Mathf.Repeat(Time.time * halfScrollSpeed, tileSize);
newPosition = new Vector2(-floatNewPosition, 0f);
transform.position = startPosition + newPosition;
}
}
}
I was thinking a Vector2.Lerp might do it, but it's super buggy when I try it every time (and I tried Vector2.SmoothDamp as well, and same thing there too :( What am I doing wrong? Or, am I missing something else that I could use?
bump. I'm not looking for someone to write the code, just fairly general advice will work! :)
Lerp from current position to destination. It will slow down gradually as the distance gets shorter. If a lerp takes the scroller 1/2 way everytime, It will gradually slow down:
@JackThe$$anonymous$$reator I did, and I tried Vector2.SmoothDamp, and either way it gets really super buggy.
@JackThe$$anonymous$$reator just to show -
void Update ()
{
if (!script.scrollerThing)
{
float floatNewPosition = $$anonymous$$athf.Repeat(Time.time * scrollSpeed, tileSize);
newPosition = new Vector2(-floatNewPosition, 0f);
//transform.position = startPosition + newPosition;
transform.position = Vector2.Lerp(startPosition, newPosition, 0.5f);
@JackThe$$anonymous$$reator And one more thing I should note - I do have this same script tied to other objects to achieve a parallax effect (giving the ground, foreground, and floor different speeds and so forth). HOWEVER, I tried putting the lerp on one particular set (floor) and what it does is it moves the object to a different y value (odd), and it kinda works (slows it down pretty good), but then it also kicks it over after it has finished pulling it. So, I tried Time.deltaTime (ins$$anonymous$$d of the 0.5f value), and the floor just sits there and acts kind of buggy.
I'm not sure what the newPosition here is supposed to do (didn't test it), I'm guessing it moves up to tileLength and then resets to 0 and starts again?
If so, I think changing it to something like this might work, as I'm guessing the above causes your newPosition to jump to a see$$anonymous$$gly random position at the moment you change scrollSpeed.
private Vector2 startPosition;
privae float newPosition = 0;
void Update ()
{
newPosition += Time.deltaTime * scrollSpeed;
while (newPosition >= tileSize) newPosition -= tileSize;
transform.position = startPosition + (Vector2.left * newPosition);
}
Changing the value of scrollSpeed here shouldn't cause "Choppy" behaviour I guess. (If I understand what you mean with "Choppy" :p). How much the speed will drop obviously depends on the change of scrollSpeed
@troien Unfortunately, That didn't really do anything beneficial. To better explain newPosition - I updated the script :) Please see above.
I just tested it now, and I believe I actually understood you correctly. And when I try your code vs the code I provided, the 'reset' (which I call see$$anonymous$$gly random jump in my comment above) you talk about in your question is gone whe I use my code.
The code I tested was this:
public class ScrollTest : $$anonymous$$onoBehaviour
{
public float scrollSpeed;
public float halfScrollSpeed;
public float tileSize;
public bool halfSpeed; // I use this ins$$anonymous$$d of your script.scrollerThing
Vector2 startPosition;
private float newPosition = 0;
// Use this for initialization
void Start()
{
startPosition = transform.position;
}
// Update is called once per frame
void FixedUpdate()
{
if (!halfSpeed)
newPosition += Time.deltaTime * scrollSpeed;
else
newPosition += Time.deltaTime * halfScrollSpeed;
while (newPosition >= tileSize) newPosition -= tileSize;
transform.position = startPosition + (Vector2.left * newPosition);
}
}
If it doesn't give you what you want, then I really don't know what you mean with that reset, as this code does fix at least one which you should be able to see the difference for certain :p
Answer by troien · Apr 22, 2016 at 04:47 PM
Ok, so my answer, based on earlier comments
In your old script you did this:
float floatNewPosition = Mathf.Repeat(Time.time * scrollSpeed, tileSize);
This causes floatNewPosition to jump to a seemingly random position whenever you change scrollSpeed. This is because Mahf.Repeat is bascally a modulo. Which means, devide the value on the left by the value on the right and return the rest value of that devision. If you in one frame change your scrollSpeed, you multiply Time.time by another value. That causes the result to do a 'seemingly random' jump. As Time.time is the time sinse startup, and if you multiply this by another value, well, you'll get a completely different result. After you changed scrollspeed though and this jump has occured it will behave as expected, as from then on time (and thus also the increase in time) is multiplied by the new multiplier.
When you change it to this:
newPosition += Time.deltaTime * scrollSpeed;
And store newPosition as a private variable, you don't have this problem because all you are ever multiplying here is the increase in time, as opposed to the time sinse you started the game. So now when you change scrollSpeed this frame, newPosition will not randomly jump and then increase at a different speed, but instead it will only increase at a different speed.
Ofcourse to add the efect that modulo has of resetting to 0 when you reach tileSize, you'll now have to add a simple while loop like so
while (newPosition >= tileSize) newPosition -= tileSize;
And The remainder of what you did doesn't realy change.
So the resulting code could be:
public class ScrollTest : MonoBehaviour
{
public float scrollSpeed;
public float halfScrollSpeed;
public float tileSize;
public bool halfSpeed; // I use this instead of your script.scrollerThing
Vector2 startPosition;
private float newPosition = 0;
// Use this for initialization
void Start()
{
startPosition = transform.position;
}
// Update is called once per frame
void FixedUpdate()
{
if (!halfSpeed)
newPosition += Time.deltaTime * scrollSpeed;
else
newPosition += Time.deltaTime * halfScrollSpeed;
while (newPosition >= tileSize) newPosition -= tileSize;
transform.position = startPosition + (Vector2.left * newPosition);
}
}
Thank you! Your code looks way more elegant than $$anonymous$$e! ;) And now I know when/why to use a while loop.
Your answer
Follow this Question
Related Questions
Slow Motion Physics Lag Spikes 0 Answers
Slow motion problem 1 Answer
parallax scrolling background 2 Answers
Problem with 2D parallax effect (flickering) 1 Answer
Detect scene out of camera. 1 Answer