Clouds are here!

Sometimes as a game developer you don't feel like working in the really important stuff. Sometimes you simply want to spend hours obsessed on getting some small detail right that doesn't add a lot to gameplay but you do it anyway because it's fun to implement it. That was exactly the case yesterday, when I decided to implement a cloud layer when you zoom out in the map. The final result is something like this:


So, here is how I faced this pretty useless task.

Step 1: Generating some cloud textures

The first thing I did was open Photoshop and generate a few different cloud textures. In order to accomplish this I used the "render -> clouds" option and then put a mask in front of it where I drew random shapes and then applied some gaussian blur. The end result is something like this:


Step 2: Making a cloud prefab

The next thing, after importing the textures in Unity, was to build a cloud prefab. I don't need volumetric clouds for this game - after all, they will only be seen when you zoom out over them with the camera looking almost straight down. So the decision was simple: the clouds are simply going to be a plane mesh with the cloud texture and the Particles/Alpha Blended shader. I also added a small script that handles the movement of the clouds in accordance with the wind direction and speed.

Step 3: Manage those clouds

I also added a very small CloudController class that generates a few clouds (each with a random texture) in random places and if some of them gets too far away from the map it gets removed and replaced with a new one. Here is the code of the CloudController, in case you are wondering about it:

#pragma strict

import System.Collections.Generic;

public var windManager : WindManager;
public var cloudPrefab : Cloud;
public var maxClouds : int;
public var minCloudHeight : float = 800.0f;
public var maxCloudHeight : float = 1200.0f;
public var maxCloudDistance : float = 13000.0f;
public var cloudMaterials : Material[];
private var clouds : List.<Cloud> = List.<Cloud>();

function Update () {
RemoveDeadClouds();
AddClouds();
}

function RemoveDeadClouds() {
var cloudsToRemove = List.<Cloud>();
var centerOfWorld = Vector3(5000, 1500, 5000);
// check which clouds are scheduled for deletion because they are too far from the center
for (var cloud in clouds) {
if (Vector3.Distance(centerOfWorld, cloud.transform.position) > maxCloudDistance) {
cloudsToRemove.Add(cloud);
}
}
for (var cloudToRemove in cloudsToRemove) {
clouds.Remove(cloudToRemove);
Destroy(cloudToRemove.gameObject);
}
}

function AddClouds() {
while (clouds.Count < maxClouds) {
var xPos = Random.Range(0.0f, 10000.0f);
var yPos = Random.Range(minCloudHeight, maxCloudHeight);
var zPos = Random.Range(0.0f, 10000.0f);
var newCloud : Cloud = Instantiate(cloudPrefab) as Cloud;
newCloud.windManager = windManager;
newCloud.gameObject.transform.position = Vector3(xPos, yPos, zPos);
newCloud.gameObject.transform.localEulerAngles.y = Random.Range(0.0f, 360.0f);
// assign a random cloud material
var mr : MeshRenderer = newCloud.gameObject.GetComponent(MeshRenderer);
mr.material = cloudMaterials[Random.Range(0, cloudMaterials.Length)];
clouds.Add(newCloud);
}
}

And that's it! I think the end result is pretty nice and with very little effort! Now, onwards to spend time in more useful features of the game! :)

Comentarios