Now Playing Tracks

C# perlin noise clouds script for Unity3D

A fellow tumblerista asked me if the perlin noise cloud script could be purchased somewhere… well, no: it’s free :-)

image

image

Code Clouds.cs

using UnityEngine;
using System.Collections;

public class Clouds : MonoBehaviour {
	
	Texture2D texture;
	
	public int width = 128;
	public int height = 128;
	
	public Color cloudColor = Color.white;
	
	public float scale = 5f;
	public int octaves = 6;
	public float persistence = 0.6f;
	public int seed = 0;
	
	public float contrastLow = 0f;
	public float contrastHigh = 1f;
	public float brightnessOffset = 0f;
	
	public float xSpeed = 0.001f;
	public float ySpeed = 0.0005f;
	
	// Start
	void Start () {
	
		texture = new Texture2D(width, height, TextureFormat.ARGB32, false);
		renderer.material.mainTexture = texture;
		
		GenerateCloudNoise(width, height);
	}
	
	// Update
	void Update () {
				
		renderer.material.mainTextureOffset = new Vector2(renderer.material.mainTextureOffset.x + xSpeed, renderer.material.mainTextureOffset.y + ySpeed);
	}
	
	// Generate cloud noise
	void GenerateCloudNoise(int noiseWidth, int noiseHeight) {
	
		float[,] perlinNoise = PerlinNoise.GeneratePerlinNoise(seed, octaves, persistence, noiseWidth, noiseHeight);
		float noiseValue;
		
		for(int y = 0; y < noiseWidth; y++) {
			
			for(int x = 0; x < noiseHeight; x++) {
				
				noiseValue = perlinNoise[x, y];
				noiseValue *= SimplexNoise.SeamlessNoise((float) x / (float) width, (float) y / (float) height, scale, scale, 0f);

				noiseValue = Mathf.Clamp(noiseValue, contrastLow, contrastHigh + contrastLow) - contrastLow;
				noiseValue = Mathf.Clamp(noiseValue, 0f, 1f);
				
				float r = Mathf.Clamp(cloudColor.r + brightnessOffset, 0f, 1f);
				float g = Mathf.Clamp(cloudColor.g + brightnessOffset, 0f, 1f);
				float b = Mathf.Clamp(cloudColor.b + brightnessOffset, 0f, 1f);
				
				texture.SetPixel(x, y, new Color(r, g, b, noiseValue));
			}
		}
		
		texture.Apply();
	}
}

Hope you enjoy the script, let me know if you add some major improvements…

Download the example package 

Credits

Perlin noise, smooth noise and white noise by Herman Tulleken

Simplex noise by Ilya Suzdalnitski

C# Messenger for Unity3D (compatible with Flash export)

Aren’t there already enough messenger/notification systems for Unity? Yes, but most of them don’t work with Flash export (which is sometimes required by clients)…

I decided to give it a try and the result is simply awesome! Well, maybe not awesome, but it works very well! We will need two scripts:

Code Messenger.cs

using UnityEngine;
using System.Collections;

public class Messenger : MonoBehaviour {
    
	static ArrayList subscriptions;
	
	// Awake
	void Awake() {

		subscriptions = new ArrayList();
	}
	
	// Add listener
	public static void Subscribe(GameObject subscriber, string subscription, string callback) {

		MessengerSubscription subscriptionToAdd = new MessengerSubscription();
		
		subscriptionToAdd.subscriber = subscriber;
		subscriptionToAdd.subscription = subscription;
		subscriptionToAdd.callback = callback;
		
		bool subscriptionExists = false;
		
		for(int i = 0; i < subscriptions.Count; i++) {
		
			if(CompareSubscriptions(subscriptions[i] as MessengerSubscription, subscriptionToAdd)) {
				
				subscriptionExists = true;
			}
		}
		
		if(!subscriptionExists) {
			
			subscriptions.Add(subscriptionToAdd);
		}
	}
	
	// Remove listener
	public static void Unsubscribe(GameObject subscriber, string subscription, string callback) {

		MessengerSubscription subscriptionToRemove = new MessengerSubscription();
		
		subscriptionToRemove.subscriber = subscriber;
		subscriptionToRemove.subscription = subscription;
		subscriptionToRemove.callback = callback;
				
		for(int i = 0; i < subscriptions.Count; i++) {
		
			if(CompareSubscriptions(subscriptions[i] as MessengerSubscription, subscriptionToRemove)) {
				
				subscriptions.RemoveAt(i);
			}
		}
	}
	
	// Broadcast without values
	public static void Broadcast(string subscription) {

		foreach(MessengerSubscription messengerSubscription in subscriptions) {
		
			if(messengerSubscription.subscription == subscription) {
				
				messengerSubscription.subscriber.SendMessage(messengerSubscription.callback, SendMessageOptions.DontRequireReceiver);
			}
		}
	}
	
	// Broadcast with values
	public static void Broadcast(string subscription, object value) {

		foreach(MessengerSubscription messengerSubscription in subscriptions) {
		
			if(messengerSubscription.subscription == subscription) {
				
				messengerSubscription.subscriber.SendMessage(messengerSubscription.callback, value, SendMessageOptions.DontRequireReceiver);
			}
		}
	}
	
	// Compare subscriptions
	static bool CompareSubscriptions(MessengerSubscription first, MessengerSubscription second) {
	
		if(first.subscriber == second.subscriber && first.subscription == second.subscription && first.callback == second.callback) {
			
			return true;
		}
		
		return false;
	}
	
	// Debug subscriptions
	public static void DebugSubscriptions() {
				
		foreach(MessengerSubscription debugSubscription in subscriptions) {
		
			Debug.Log(debugSubscription.subscriber.name + " " + debugSubscription.subscription + " " + debugSubscription.callback);
		}
	}
}

Code MessengerSubscription.cs

using UnityEngine;
using System.Collections;

public class MessengerSubscription {
    
	public GameObject subscriber;
	public string subscription;
	public string callback;
}

Wait, you’re using SendMessage?

Yup, I do. The problem with SendMessage itself is: you can only send messages to objects you know (or their children or their parents). This means you always have to store and update a list of GameObjects which can quickly become a mess.

This is exactly what my messenger script does in a comfortable way. You can focus on subscribing and broadcasting, the script manages the list for you.

However, SendMessage is apparently not really fast. Messenger.cs is probably not suited for handling thousands of subscribers. While a native C# event handling approach would be preferable, this script has to work with Flash export (must-have feature for me). This is why I’m using SendMessage.

Functionality

Now, what can you do with these scripts?

  • subscribe a GameObject to a message list
  • unsubscribe it from a message list
  • broadcast a message without passing variables
  • broadcast a message, passing one or more variables (multiple variables are passed inside an object or an array, so basically it is still one variable/object, but it can hold more than one value)

That’s it? No! There’s more:

  • subscribe a GameObject to a message list and route it to more than one callback function
  • unsubscribe only some of the callback functions of that GameObject

Setup

To get this messenger working, you simply have to create an empty GameObject and assign the Messenger.cs script to it. The MessengerSubscription.cs script should not be assigned to anything.

Examples

Subscribing

// Messenger.Subscribe(GameObject subscriber, string subscription, string callback);
Messenger.Subscribe(gameObject, "Pause", "OnPause");

Unsubscribing

// Messenger.Unsubscribe(GameObject subscriber, string subscription, string callback);
Messenger.Unsubscribe(gameObject, "Pause", "OnPause");

Broadcasting without values

// Messenger.Broadcast(string subscription);
Messenger.Broadcast("Pause");

Broadcasting with values

// Messenger.Broadcast(string subscription, value object);
Messenger.Broadcast("Pause", 10f);

Debugging subscriptions

// Prints a list of all subscriptions
Messenger.DebugSubscriptions();

Download the example package 

Troubleshooting

As this script doesn’t have any error handling routines yet, it may show some weird errors from time to time. In this case, remove the Messenger.cs component from the GameObject and simply assign it again.

Roadmap

  • fix weird editor mode bug (see above)
  • add error/exception handling
  • make it faster

Nostalgia XXI: Starship Titanic poster blowup (Photoshop)

Starship Titanic is a book and a game which had outstanding graphics for its time. The book was written by Terry Jones (based on an idea by Douglas Adams), the game was produced by Douglas Adams.

Oscar Chichoni is an illustrator. There’s an official game page as well as an “Starship Titanic Construction Intranet" page.

Base image (1041 x 1354 px):

image

Typo reference (627 x 785 px):

image

The final blowup image (5906 x 7693 px):

image

Detail:

image

Looks good on my wall (60 x 100 cm):

image

Original artwork © 1997 Oscar Chichoni
Starship Titanic book © 1997 Terry Jones, Douglas Adams
Starship Titanic game © 1997 Douglas Adams, The Digital Village

Procedural cloud textures in Unity3D

Hey y’all, finally something new :D

I made a C# script creating 2D cloud textures at runtime.

Advantages

- not a single image file is required
- infinite variations
- tweakable at runtime

Disadvantages

- certain cloud types are hard to recreate with the current version
- noise computation consumes quite a lot of performance (heavily depending on the size of the noise texture)

image

The script creates four types of noises: white noise, smooth noise, Simplex noise and Perlin noise. At the end, the Simplex and Perlin noise are combined into a single image (white and smooth noise are required for computing the other noises).

image

By changing parameters like scale, number of octave, persistence and others the script generates quite different types of cloud textures.

image

image

image

image

image

Unity3D playground: random features

Random placement of debris on a surface

My RandomPlacementOnSurface script clones and places objects randomly at runtime. The objects are placed inside a box collider which raycasts random positions onto a surface (e.g. the floor). This works with uneven surfaces, too.

image

In game mode, debris is placed randomly on the surface:

image

Code RandomPlacementOnSurface.cs

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(BoxCollider))]

public class RandomPlacementOnSurface : MonoBehaviour {
   
    Vector3 originalScale = new Vector3(1f, 1f, 1f);
       
    public GameObject objectToPlace;
    public int numberOfClones = 1;
   
    public Vector3 randomScale = new Vector3(0.2f, 0.2f, 0.2f);
    public Vector3 randomRotation = new Vector3(0f, 0f, 0f);
    public Vector3 additionalRotation = new Vector3(0f, 0f, 0f);
   
    // Initialization
    void Awake() {
       
    }
   
    // Start
    void Start() {
   
        // Return if necessary objects are not defined
        if(!objectToPlace) {
           
            return;   
        }
       
        // Store original scale
        originalScale = objectToPlace.transform.localScale;
       
        // Create numberOfClones clones
        for(int i = 0; i < numberOfClones; i++) {
           
            Place(i);
        }
    }
   
    // Place randomly
    void Place(int cloneNumber) {
       
        // Create random position inside collider
        Vector2 random = Random.insideUnitCircle;
        float x = random.x * collider.bounds.extents.x + transform.position.x;
        float y = collider.bounds.extents.y + transform.position.y;
        float z = random.y * collider.bounds.extents.z + transform.position.z;
               
        RaycastHit hit;
       
        // Get raycasted point or return when no hit is available
        if(Physics.Raycast(new Vector3(x, y, z), Vector3.down, out hit, collider.bounds.size.y)) {
       
            y = hit.point.y;
        } else {
       
            return;
        }
       
        // Randomize rotation
        float rotationX = Random.Range(-1f * randomRotation.x, randomRotation.x);
        float rotationY = Random.Range(-1f * randomRotation.y, randomRotation.y);
        float rotationZ = Random.Range(-1f * randomRotation.z, randomRotation.z);
       
        // Randomize scale
        float scaleX = originalScale.x + Random.Range(-1f * randomScale.x, randomScale.x);
        float scaleY = originalScale.y + Random.Range(-1f * randomScale.y, randomScale.y);
        float scaleZ = originalScale.z + Random.Range(-1f * randomScale.z, randomScale.z);
       
        // Place objectToPlace first, then create clones if necessary
        if(cloneNumber == 0) {
           
            objectToPlace.transform.position = new Vector3(x, y, z);
            objectToPlace.transform.rotation = Quaternion.Euler(new Vector3(rotationX, rotationY, rotationZ) + additionalRotation);   
            objectToPlace.transform.localScale = new Vector3(scaleX, scaleY, scaleZ);
        } else {
           
            GameObject instance = Instantiate(objectToPlace, new Vector3(x, y, z), Quaternion.Euler(new Vector3(rotationX, rotationY, rotationZ) + additionalRotation)) as GameObject;
            instance.transform.parent = gameObject.transform;
            instance.transform.localScale = new Vector3(scaleX, scaleY, scaleZ);
        }
    }
}

Random animation

My RandomAnimation script randomly animates an object within user-specified bounds.

image

Code RandomAnimation.cs

using UnityEngine;
using System.Collections;

public class RandomAnimation : MonoBehaviour {
   
    Hashtable optional;
   
    public bool move = true;
    public bool rotate = false;
    public bool scale = false;
    public bool loop = true;
   
    public float interval = 10f;
   
    public Vector3 minPosition = new Vector3(0f, 0f, 0f);
    public Vector3 maxPosition = new Vector3(0f, 0f, 0f);
   
    public Vector3 minRotation = new Vector3(0f, 0f, 0f);
    public Vector3 maxRotation = new Vector3(0f, 0f, 0f);
   
    public Vector3 minScale = new Vector3(0f, 0f, 0f);
    public Vector3 maxScale = new Vector3(0f, 0f, 0f);
   
    // Initialization
    void Awake() {
       
        // Tweak tween
        optional = new Hashtable();
        optional.Add("ease", LeanTweenType.linear);
       
        if(loop) {
               
            optional.Add("onComplete", "Animate");
            optional.Add("onCompleteTarget", gameObject);
        }
    }
   
    // Start
    void Start() {
       
        Animate();
    }
   
    // Animate randomly
    void Animate() {
       
        LeanTween.cancel(gameObject);
       
        if(move) {
           
            Vector3 target = new Vector3(Random.Range(minPosition.x, maxPosition.x), Random.Range(minPosition.y, maxPosition.y), Random.Range(minPosition.z, maxPosition.z));
            LeanTween.move(gameObject, target, interval, optional);
        }
       
        if(rotate) {
           
            Vector3 target = new Vector3(Random.Range(minRotation.x, maxRotation.x), Random.Range(minRotation.y, maxRotation.y), Random.Range(minRotation.z, maxRotation.z));
            LeanTween.rotate(gameObject, target, interval, optional);
        }
       
        if(scale) {
           
            Vector3 target = new Vector3(Random.Range(minScale.x, maxScale.x), Random.Range(minScale.y, maxScale.y), Random.Range(minScale.z, maxScale.z));
            LeanTween.scale(gameObject, target, interval, optional);
        }
    }
}

As always, the code is ‘work in progress’ and far from complete…

Unity3D playground: ‘Time of Day’ system

I’m trying to create a time of day system which should contain the following features:

- Movement of sun and moon
- Moving clouds in several layers
- Changing fog, atmosphere and background color
- Moving stars at night
- Control colors and brightness values with color ramps

There’s still a lot of tweaking to do (especially color and brightness values), but I am quite satisfied with the progress of my weekend project :)

Color and brightness ramps

Screenshots

To Tumblr, Love Pixel Union