Bloodirony Blog


Blog

INSIGHTS, TUTORIALS AND DIRTY SECRETS

Viewing entries tagged
unity2d

How to create a random tileset in Unity2D

2 Comments

How to create a random tileset in Unity2D

When it comes to the background, classic shmups usually use something like infinite scrolling. Because we are not making a normal shmup with spaceships and other flying stuff we wanted to handle this completely different.

Therefore we created a static background, which is not moving during the actual battle. To give the user some feedback regarding progress, we also move the background after defined waves or a boss fight.

To avoid creating hundreds of full sized background assets we thought of randomly create these backgrounds out of a tileset image.


This is actually quite easy, the only thing you need is a image with a defined grid of single tiles. Next thing you will need is something to draw the tiles on. I used the unity plane component with a mesh renderer for that.

First step, initialize the mesh:

int numTiles = size_x * size_y;
int numTris = numTiles * 2;

int vsize_x = size_x + 1;
int vsize_y = size_y + 1;
int numVerts = vsize_x * vsize_y;

Vector3[] vertices = new Vector3[ numVerts ];
Vector3[] normals = new Vector3[numVerts];
Vector2[] uv = new Vector2[numVerts];

int[] triangles = new int[ numTris * 3 ];

int x, z;
for(z=0; z < vsize_y; z++) {
    for(x=0; x < vsize_x; x++) {
        vertices[ z * vsize_x + x ] = new Vector3( x*tileSize, 0, -z*tileSize );
        normals[ z * vsize_x + x ] = Vector3.up;
        uv[ z * vsize_x + x ] = new Vector2( (float)x / size_x, 1f - (float)z / size_y );
    }
}

for(z=0; z < size_y; z++) {
    for(x=0; x < size_x; x++) {
        int squareIndex = z * size_x + x;
        int triOffset = squareIndex * 6;
        triangles[triOffset + 0] = z * vsize_x + x +           0;
        triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 0;
        triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 1;

        triangles[triOffset + 3] = z * vsize_x + x +           0;
        triangles[triOffset + 5] = z * vsize_x + x + vsize_x + 1;
        triangles[triOffset + 4] = z * vsize_x + x +           1;
    }
}

// Create a new Mesh and populate with the data
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;

// Assign our mesh to our filter/renderer/collider
MeshFilter mesh_filter = plane.GetComponent();
MeshCollider mesh_collider = plane.GetComponent();

mesh_filter.mesh = mesh;

 

Next step, split your background image into single tiles:

private Color[][] SplitTiles() {
    int numTilesPerRow = texture.width / tileResolution;
    int numRows = texture.height / tileResolution;

    Color[][] tiles = new Color[numTilesPerRow*numRows][];

    for(int y=0; y < numRows; y++) {
        for(int x=0; x < numTilesPerRow; x++) {
            tiles[y*numTilesPerRow + x] = texture.GetPixels( x*tileResolution , y*tileResolution, tileResolution, tileResolution );
        }
    }

    return tiles;
}


Final step, draw your random tiles on the mesh:

int texWidth = size_x * tileResolution;
int texHeight = size_y * tileResolution;
Texture2D newTexture = new Texture2D(texWidth, texHeight,texture.format, false);

Color[][] tiles = SplitTiles();

for(int y=0; y < size_y; y++) {
    for(int x=0; x < size_x; x++) {
        Color[] p = tiles[Random.Range(0, 30)];
        newTexture.SetPixels(x*tileResolution, y*tileResolution, tileResolution, tileResolution, p);
    }
}
newTexture.anisoLevel=1;
newTexture.mipMapBias=0f;
newTexture.filterMode = FilterMode.Point;
newTexture.wrapMode = TextureWrapMode.Clamp;
newTexture.Apply();

MeshRenderer mesh_renderer = _plane.GetComponent();
mesh_renderer.sharedMaterials[0].mainTexture = newTexture;

With a shader on top the final result looks like this

Download Unity 5 Sample Project

As with every previous tutorial, we provide you with a sample project for Unity 5.

2 Comments

The Art of Screenshake in Unity2D

Comment

The Art of Screenshake in Unity2D

Due to the fact that our Big Bad Bearded Boss is a huge Vlambeer fan, my first task was to watch the presentation of Vlambeers Jan Willem Nijman Gamefeel. JW showed 30 little tricks to make your action game more fun. This post is about how to implement some of this tricks in Unity for our upcoming game Shooting Stars.

Screenshake

Let's start with the screenshake effect. The main approach is to shake the camera randomly in special moments of the game. For example on a bullet impact or an explosion. My first attempt to get this done was using iTweens ShakePosition(). The effect itself was really cool, BUT there was a problem with multiple screenshakes at the same time using ShakePosition(), so I started to implement my own solution:

private Vector3 cameraStartPosition;
private float shakeAmountX;
private float shakeAmountY;
private float time;
bool reset=true;

public void Init () {
    cameraStartPosition=Camera.main.gameObject.transform.position;
    InvokeRepeating("CameraShake", 0, .01f);
}

public void ScreenShake(float amountX, float amountY, float _time){
    if(amountX>shakeAmountX){
        shakeAmountX = amountX;
    }

    if(amountY>shakeAmountY){
        shakeAmountY = amountY;
    }
    if(_time>time){
        time=_time;
    }
    reset=false;    
}

public void ScreenShake(float amount, float _time){
    if(amount>shakeAmountX && amount>shakeAmountY){
        shakeAmountX = amount;
        shakeAmountY = amount;
    }
    if(_time>time){
        time=_time;
    }
    reset=false;
}

void CameraShake(){
    if(shakeAmountX>0 && shakeAmountY>0 && time>0) {
        time-=.01f;
        float quakeAmtX = UnityEngine.Random.value*Mathf.Sin( shakeAmountX)*2 - shakeAmountX;
        float quakeAmtY = UnityEngine.Random.value*Mathf.Sin(shakeAmountY)*2 - shakeAmountY;
        Vector3 pp = cameraStartPosition;
        pp.y+= quakeAmtY; // can also add to x and/or z
        pp.x+= quakeAmtX;
        Camera.main.transform.position = pp;
    }else if(!reset){
        Camera.main.transform.position=cameraStartPosition;
        reset=true;
    }
}

Kickback on Shoot

Another thing I wanted to implement is a little kickback whenever our main character is shooting lazers, bullets or whatever. Due to the fact that our game is a vertical shootemup this was quite easy to implement. Whenever our main character is shooting I manipulate his y position by a small random amount:

targetPosition.y=targetPosition.y-UnityEngine.Random.Range (0.1f, 0.3f);

Permanence

I also thought about implementing some permanence. So I decided to make our “lazer shells” permanent. First of all I created a flight path for our shells by using iTweens MoveTo(). Not really satisfied with the result I added some rotation to the shells by using RotateBy(). After the movement of our shells is over the GameObjects will stay whereever they moved to. The problem is, that after some minutes of constantly shooting, you have a lot of shells lying around. This is not a problem for the PC or Mac version, but will be a problem for mobile devices due to limited amount of available Memory. So for performance reasons I have to destroy the shells (or move them back to a pool) after some time.

float height=UnityEngine.Random.Range (0.2f, 0.7f);
iTween.MoveTo(gameObject, iTween.Hash("path",new Vector3[]{
    new Vector3(transform.position.x+0.4f,transform.position.y+height,0), 
new Vector3(transform.position.x+height+0.2f,transform.position.y-0.4f,0)}, "time",1,"easetype",iTween.EaseType.linear));
iTween.RotateBy(gameObject, iTween.Hash(
    "name", "ShellRotation", "looptype",iTween.LoopType.none, "z", Random.Range(-6f, 6f), "time",  0.9f));
Destroy (gameObject, 10f);

What's next?

Because of problems with permanence, missing image effects, etc. we consider switching from the free version to Unity Pro. Come back soon, if you want to know which way we will go.

Comment