Pages

Saturday, May 21, 2011

Unity3d + C#: 2D game background scrolling and percentage sign...

In 2d game development, they are lot of times where you would want the background texture (tile-able) of your game to scroll while your character is "running" (where in fact he wasn't), to make it looks like he's really running across the scene.

(screenshot from Canabalt)

Well, Unity provided some basic tips on making the textures on a plane to scroll in accordance to time. Here are the two main methods they used:
public float scrollSpeed = 0.5F;

void Update() {
float offset = Time.time * scrollSpeed;
renderer.material.mainTextureOffset = new Vector2(offset, 0);
}

public float scrollSpeed = 0.5F;

void Update() {
float offset = Time.time * scrollSpeed;
renderer.material.SetTextureOffset("_MainTex", new Vector2(offset, 0));
}

What they are doing here is that, they take the offset value (Vector2) of the texture in the material of your background (usually a plane in the scene), and then set or add values in one of its axis (which is the above case, it's the X-axis), and the texture will scroll as if it were moving...

It's a good method for not only moving the background of your 2d game, but also commonly used for making a force field effect (like in Unity's own 3rd person controller tutorial), special magic-attack effect (like those in MMO), etc... a lot can be done with this two texture-scrolling method.

However, if you're making a game where the background of your game will continuously scroll for as long as your character run (let's say that particular level is about 5 minutes long), you might wanna do some adjustment with the script.

Here's what happen, in the game which I'm currently developing, I too have a character flying up in the scene, and the background is continuously scrolling down (to make it looks like it was flying up)... and will only stop until the level is complete. But as time goes by (about 10 minutes or more of continuous gameplay), the background texture of my game become more and more pixelated... or blocky...

Looking back at the script (above) which Unity provide:
float offset = Time.time * scrollSpeed;
renderer.material.SetTextureOffset("_MainTex", new Vector2(offset, 0));

If you try printing the 'offset' variable (using print() or Debug.Log()), you'll notice that once the game starts, the offset will continuously increase, and get above the value of 1... which is why the blurry/pixelated problem occurs here. The UV value of the offset should always stay as close as one. If anything more, the texture will 'hypothetically' multiplying, stretching or whatever you call it... making it more and more pixelated.


The way to solve this is to always set the value of 'offset' to a range between 0 to 1. To do this, all you have to do is to divide the value of 'offset' by the percentage sign:
float offset = Time.time * scrollSpeed;
offset = offset % 1; // divide using the percentage sign...
renderer.material.SetTextureOffset("_MainTex", new Vector2(offset, 0));

Not sure if I'm explaining this correctly, but the sign was kinda like keeping your value at a percentage of the max value of your choice, which in this case is 1.

The percentage sign was also commonly used at formatting the time (minutes, seconds, etc):
public int format = 60;
private float timer = 0.0f;
private int sec;
private int min;

void Update()
{
    timer += Time.deltaTime;

    sec = (int)(timer % format);

    min = (int)(timer / format);

    print(min + ": " + sec); // this is a sample time formatting script...
}

No comments: