Create rain in Unity and upload to STYLY

I explain how to create rain with Unity and upload it to STYLY.

※You can access the sample project from


A sample of rain by Vertex Shader in Unity


How to create rain

Before creating rain, I give an overview of how to create it.

It requires 3 STEPS as shown below.

  1. Create a lot of triangular meshes.
  2. Shake the triangular meshes arranged at high speed.
  3. Adjust the colour to make them look like rain (Completion).

Create a lot of triangular meshes


Create triangular meshes by a program

I arranged a lot of fine triangular meshes so that they fill a cube.

Shake the triangular meshes at high speed


Shake the triangular meshes by Vertex Shader

Shake the vertices by Vertex Shader

Adjust the colour to make them look like rain (completion)


Adjust the colour to make them look like rain. It completes the modelling.

Colour the meshes in translucent light blue to make them look like rain. It completes modelling rain.


Create meshes

From now, I explain the actual steps to model rain.


Firstly, we create meshes.


Create a lot of triangular meshes by a program


This time, we use two C# scripts to create triangular meshes.

I explain how to add two C# scripts here.


Script 1: Create RandomMesh.cs

Firstly, right-click in the Project window to create a C# script.


Create a C# script


Rename it RandomMesh.


Check the script created.


Open the script, RandomMesh, and edit it as shown below.

using UnityEngine;
using System.Collections.Generic;

public class RandomMesh : MonoBehaviour
    const string k_MeshName = "[Generated]RainMesh"; // Mesh Name
    [SerializeField, Header("The number of raindrops")] int m_TriangleCount = 1500; // The number of triangular meshes
    [SerializeField, Header("The size of raindrop")] float m_TriangleScale = 0.3f; // The size of triangular meshes
    [SerializeField, Header("The randomness of rain")] Vector3 m_TriangleRange = new Vector3(4f, 4f, 4f); // The randomness of rain
    [SerializeField, HideInInspector] string m_OnCreateText = "No mesh information\n Update Mesh";

    public int TriangleCount { get { return m_TriangleCount; } }
    public float TriangleScale { get { return m_TriangleScale; } }
    public Vector3 TriangleRange { get { return m_TriangleRange; } }
    public string OnCreateText { get { return m_OnCreateText; } set { m_OnCreateText = value; } }

    /// <summary>
    /// Craete a new mesh 
    /// </summary>
    public Mesh CreateNewMesh()
        Vector3[] vertices = new Vector3[m_TriangleCount * 3]; // The coordinates of vertex
        int[] triangles = new int[m_TriangleCount * 3]; // The index of vertex
        Vector3[] normals = new Vector3[vertices.Length];
        int pos = 0;
        for (int i = 0; i < m_TriangleCount; i++)
            var v1 = Vector3.Scale(new Vector3(Random.value, Random.value, Random.value) - * 0.5f, m_TriangleRange);
            var v2 = v1 + new Vector3(Random.value - 0.5f, 0f, Random.value - 0.5f) * m_TriangleScale;
            var v3 = v1 + new Vector3(Random.value - 0.5f, 0f, Random.value - 0.5f) * m_TriangleScale;

            vertices[pos + 0] = v1;
            vertices[pos + 1] = v2;
            vertices[pos + 2] = v3;
            pos += 3;

        for (int i = 0; i < triangles.Length; i++)
            triangles[i] = i;

        for (int i = 0; i < normals.Length; i++)
            normals[i] = new Vector3(0f, 1f, 0f);
        //Create a mesh
        var mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.normals = normals;

        return mesh;


It completes the RandomMesh script.


Script2: Create RandomMeshInspector.cs

In the same way, create a script, RandomMeshInspector, as well.


Open the script.


Edit the content of the RandomMeshInspector script as shown below.

using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.IO;

// Customize Editor
public class RandomMeshInspector : Editor
    const string k_ExportMeshName = "[Generated]RainMesh"; // The name of the mesh to save
    static readonly Color k_ButtonColor = Color.yellow;
    static readonly Color k_ButtonTextColor = Color.white;

    /// <summary>
    /// Drawing the Inspector
    /// </summary>
    public override void OnInspectorGUI()
        if (PrefabUtility.GetPrefabType(target) != PrefabType.Prefab)
            EditorGUILayout.HelpBox("You must edit settings via Prefab.", MessageType.Info);

        var defaultColor = GUI.color;
        var defaultContentColor = GUI.contentColor;

        var randomMesh = target as RandomMesh;

        // Display mesh inforamtion
        EditorGUILayout.LabelField(randomMesh.OnCreateText, GUILayout.Height(54f));

        // Change colour
        GUI.color = k_ButtonColor;
        GUI.contentColor = k_ButtonTextColor;

        if (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab)
            if (GUILayout.Button("Update Mesh"))

        // Undo
        GUI.color = defaultColor;
        GUI.contentColor = defaultContentColor;


    /// <summary>
    /// Create and save mesh
    /// </summary>
    [ContextMenu("Create Mesh")]
    void EditorCreateMesh()
        var randomMesh = target as RandomMesh;
        var meshFilter = randomMesh.GetComponent<MeshFilter>();

        // Delete the old mesh installed
        var meshAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(randomMesh));
        foreach (var meshAsset in meshAssets)
            if (meshAsset is Mesh)
                Object.DestroyImmediate(meshAsset, true);

        // Create mesh
        var newMesh = randomMesh.CreateNewMesh(); = k_ExportMeshName;
        meshFilter.sharedMesh = newMesh;

        // Install new mesh
        AssetDatabase.AddObjectToAsset(newMesh, randomMesh);

        randomMesh.OnCreateText = string.Format(
            "Mesh Information\n・The number of raindrops:{0}\n・The size of raindrops:{1}\n・The size of whole rain: {2}",

        // Save

    /// <summary>
    /// Generate the path to save mesh(at the same level as Prefab)
    /// </summary>
    string GenerateMeshPath()
        var path = AssetDatabase.GetAssetPath(target);
        var parentFullPath = Directory.GetParent(path).FullName;
        var parentPath = "Assets" + parentFullPath.Substring(Application.dataPath.Length);
        var assetPath = parentPath + Path.DirectorySeparatorChar + k_ExportMeshName; // The path to save the asset
        return assetPath;

The two C# scripts required are ready now.


Create Meshes

Next, we actually create triangular meshes.


Triangular meshes


Create a Rain object

Create a GameObject on the Hierarchy window.


Create an Empty object


Rename the object ‘Rain‘.


Rename the object.



The object renamed.


Add the RandomMesh component

Add the RandomMesh component to the Rain object.


Add the RandomMesh component


The Inspector looks the shown below after adding the component.


How the inspector looks before and after adding the component.



Check the component added.

Convert the Rain object into Prefab

Next, convert the Rain object into a Prefab.


Drag the Rain object in the Hierarchy window onto the Project window.


Create a Prefab by dragging the object onto the Project window.


A Prefab has been created.


A Prefab created


Create meshes

With the Rain prefab selected, click the ‘Update Mesh’ button on the Inspector window.


Click the button to update the mesh


A lot of triangular meshes are displayed.


Thw meshes created

Why are the meshes coloured in pink?

You can see meshes coloured in pink. That is because no material has been assigned to the MeshRenderer of the Rain object.


How they look with and without Material

Once a material is assigned, you can adjust the colour.


Assign a material to MeshRender

I will show how to assign a material to the MeshRenderer.


Expand the Materials section of the MeshRenderer.


Open ‘Materials’ by clicking the label.



Where to assign the material


Click the circular button on the Materials section to bring up the material-list window. Select the material you want to assign.


Assign the ‘Default-Diffuse’ material

Select ‘Default-Diffuse’ to assign the Default-Diffuse material to the MeshRenderer.



How the triangular meshes look after assigning the material

If assigned the Default-Diffuse material, they would be coloured in white.


Add motion to triangular meshes

Next, we add motion to the meshes to make them look like rain.


I explain how to add motion to the triangular meshes here.


Create a motion by Custom Shader

This time, we use ‘Custom Shader’ to move vertices like rain.


Combining the triangular meshes with a custom shader to render rain

Create Custom Shader

I explain how to create a custom shader here.


the Rain shader


Firstly, click ‘Create’ on the Project window (Alternatively, right-click on the Project window).


Click ‘Create’.


Select ‘Shader/Standard Surface Shader‘.

Standard Surface Shaderを選択

Select ‘Standard Surface Shader’.


A shader is created. Rename it ‘Rain‘.


Rename the shader ‘Rain’.


Edit the shader file

Open the Rain shader.


Double-click the Rain shader.


Edit Rain.shader as shown below.

Shader "Custom/Rain" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _Speed ("[VS]Rain Speed", Float) = 6.0 
        _Scale ("[VS]Rain Height", Float) = 4.0
		_Remap("[VS]Remap", Range(0.0, 1.0)) = 0.7
        _Albedo ("[FS]Rain Colour", Color) = (1.0, 1.0, 1.0, 0.5) 
        _Emission ("[FS]Rain Emission Colour", Color) = (0.0, 0.0, 0.0, 0.0) 
        _Specular ("[FS]Rain Specular Power", Range(0.0, 1.0)) = 0.5 
        _Gloss ("[FS]Rain Specular Intensity", Range(0.0, 1.0)) = 0.5 

    SubShader {
        Tags {
            "Queue" = "Transparent"
            "RenderType" = "Transparent"
        #pragma surface surf Lambert alpha
        #pragma vertex vert

        sampler2D _MainTex;

        // Function to generate random value from [0;1]
        float nhash11(float n){
            return frac(sin(n) * 43758.5453);

        // Convert the range [a;b] into [0;1]
        float remap(float t, float a, float b){
            return clamp((t-a)/(b-a), 0, 1);
        // Vertex Shader
        half _Speed;
		half _Scale;
		half _Range;
		fixed _Remap;

        // Colour
        half4 _Albedo;
        half4 _Emission;
        fixed _Specular;
        fixed _Gloss;

        // Vertex Shader Function
        void vert(inout appdata_full v) {
            fixed rnd = nhash11(fmod(v.vertex.z, 512.0)); // Random value
			//float timer = _Time.w * _Speed * remap(0.7, 1.0, rnd);
			float timer = _Time.w * _Speed * remap(_Remap, 1.0, rnd); // Convert the range [_Remap, 1.0] -> [0;1]
            v.vertex.y -= fmod(-v.vertex.y + timer, _Scale) + v.vertex.y - _Scale * 0.5;
            // v.vertex.y -= fmod(-v.vertex.y + timer, 4.0 / _Range) + v.vertex.y - _Scale * 0.5;

        struct Input {
            float2 uv_MainTex;

        // Surface Shader Function
        void surf(Input IN, inout SurfaceOutput o) {
            half4 c = tex2D(_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb * _Albedo.rgb;
            o.Emission = _Emission; 
            o.Specular = _Specular; 
            o.Gloss = _Gloss; 
            o.Alpha = _Albedo.a; 

It completes editing the shader.


Additional Note: About the filename of Shader

The shader name is ‘Rain‘ on Unity, but the actual filename is ‘Rain.shader‘.


Check the filename of the shader

You can check the filename at the bottom of the Project window.


Create Material

Next, I explain how to create a material.


Create a material from the shader


Right-click the Rain shader and select ‘Create/Material‘.


Create a material.


A material, ‘Custom_Rain’, has been created.


Check the material created.

It finishes creating a material to shake the vertices.


Test the material

Assign the Custom_Rain material created to a 3D model in the Scene.


Drag the material onto an object.


When you assign the material to a 3D model, the model moves as shown below.


The model motion after adding the material

The Custom_Rain material moves the vertices of the model so that it gives a wavy motion like this.


Check the setting of the material

Click the material to show the setting in the Inspector window.


The setting items of the material

By adjusting those values, you can change the behaviour of the material.

Add motion to rain

By combining the Custom_Rain material with the Rain object, you can make a rain-like motion.


Combining the triangular meshes and the material to render rain


I explain how to add motion to triangular meshes by assigning the material to it.


Firstly, select the Rain prefab and click the circular button on the right side of the Materials section.


Assign the material to the Rain prefab.


Select the Custom_Rain material created earlier from the material list.


Select the Custom_Rain material.


Once the Custom_Rain material is set, the motion is added then the objects move like rain.


The triangular mesh after assigning the material.

Adjust the appearance of the rain

Adjust the size and colour of the rain to make it look like realistic rain more.


Firstly, select the Custom_Rain material and click the clour-property box.


Click the colour-property box for the material.


It brings up the Color Picker window.

Set it to translucent blue-ish colour as shown below.


Set it to light blue.



The Color Picker window


When you set the colour, the rain object looks as shown below.


How the rain looks after changing the colour.

Modify the shape (The size and number of raindrops)

By adjusting the setting of the Rain prefab, you can change the size and the number of the raindrops.


The setting of the Rain prefab


Reduce the size of raindrops

By changing the ‘Raindrop Size’ value, you can change the size of the raindrops.


Modify the size of raindrops.


If you set the size to 0.1, the rain will look as shown below.


After changing the size of raindrops.

Increase the number of raindrops

You can render heavy rain by increasing the number of raindrops.


Change the number of raindrops.


By setting the number of raindrops to 6000, the rain looks as shown below.


After changing the number of raindrops


Add some randomness to the rain

You can add some randomness to the rain by increasing ‘the randomness of rain’ value.




The shown below is the rain with the randomness set to (16,4,16).


How the rain looks after changing the randomness of raindrops


Upload to STYLY

Right-click the Rain prefab and select ‘Upload prefab to STYLY’.


Upload the prefab to STYLY

It starts uploading. Wait patiently.


When you see the ‘Upload Succeeded’ window, the upload is completed.


The window pops up when the upload is completed.

See ‘My Models’ in STYLY. You will find the Rain asset uploaded there.


The prefab uploaded.


Now it’s time to make it rain on STYLY.


Place the Rain asset in STYLY.


※You can access the sample project from

newbview popup