Unityで雨を作り、STYLYへアップロードするまでの手順を解説します。 ※サンプルプロジェクトはこちらから:https://github.com/styly-dev/STYLY-Unity-Examples/tree/master/Assets/STYLY_Examples/Rain
雨の作り方の解説
雨の作成に入る前に、どうやって雨を作るのかを軽く解説いたします。 以下の3STEPで雨を作ります。
- 三角形メッシュを大量に作成
- 並べた三角形メッシュを高速で揺らす
- 色を調整すると雨っぽく見えます(完成)
三角形をメッシュを大量に作成します
立方体を埋める形で大量の細かい三角形メッシュを並べています。
三角形メッシュを高速で揺らします
頂点シェーダーで頂点を揺らします。
色味を調整すると雨っぽい(完成)
メッシュを水色の半透明にすると雨っぽい見た目になって完成です。
メッシュ作成
ここから、実際に雨を作る手順の解説をしていきます。 まずはメッシュを作成します。
準備
今回は三角形メッシュを作成するために2つのC#スクリプトを使用します。 ここでは、2つのC#スクリプトを追加する手順を解説します。
スクリプト1 : RandomMesh.cs の作成
まずはProjectウィンドウ上で右クリックしてC#スクリプトを作成します。
名前をRandomMeshにします。
スクリプトRandomMeshを開き、中身を以下のように書き換えます。
using UnityEngine; using System.Collections.Generic; [RequireComponent(typeof(MeshRenderer))] [RequireComponent(typeof(MeshFilter))] public class RandomMesh : MonoBehaviour { const string k_MeshName = "[Generated]RainMesh"; // メッシュの名前 [SerializeField, Header("雨粒の数")] int m_TriangleCount = 1500; // 三角形の個数 [SerializeField, Header("雨粒の大きさ")] float m_TriangleScale = 0.3f; // 三角形の大きさ [SerializeField, Header("雨全体のバラつき")] Vector3 m_TriangleRange = new Vector3(4f, 4f, 4f); // メッシュの大きさ [SerializeField, HideInInspector] string m_OnCreateText = "メッシュ情報がありません\nメッシュを更新してください"; 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> /// メッシュの新規作成 /// </summary> public Mesh CreateNewMesh() { Vector3[] vertices = new Vector3[m_TriangleCount * 3]; // 頂点の座標 int[] triangles = new int[m_TriangleCount * 3]; // 頂点インデックス 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) - Vector3.one * 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); } //メッシュ生成 var mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.normals = normals; return mesh; } }
スクリプトRandomMeshはこれで完成です。
スクリプト2 : RandomMeshInspector.cs の作成
同様の手順で、スクリプトRandomMeshInspectorも作成します。
スクリプトRandomMeshInspectorの中身を以下のように書き換えます。
using UnityEngine; using UnityEditor; using UnityEditor.SceneManagement; using System.IO; // エディター拡張 [CustomEditor(typeof(RandomMesh))] public class RandomMeshInspector : Editor { const string k_ExportMeshName = "[Generated]RainMesh"; // 保存するメッシュの名前 static readonly Color k_ButtonColor = Color.yellow; static readonly Color k_ButtonTextColor = Color.white; /// <summary> /// インスペクタの描画 /// </summary> public override void OnInspectorGUI() { if (PrefabUtility.GetPrefabType(target) != PrefabType.Prefab) { EditorGUILayout.HelpBox("雨の設定はPrefab上でのみ可能です。 \nYou must edit settings via Prefab.", MessageType.Info); return; } var defaultColor = GUI.color; var defaultContentColor = GUI.contentColor; var randomMesh = target as RandomMesh; // メッシュ情報 表示 EditorGUILayout.BeginVertical("Box"); EditorGUILayout.LabelField(randomMesh.OnCreateText, GUILayout.Height(54f)); EditorGUILayout.EndVertical(); // 色を変更 GUI.color = k_ButtonColor; GUI.contentColor = k_ButtonTextColor; if (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab) { if (GUILayout.Button("メッシュの更新")) { EditorCreateMesh(); } } // 元に戻す GUI.color = defaultColor; GUI.contentColor = defaultContentColor; base.DrawDefaultInspector(); } /// <summary> /// メッシュを作成し、保存する /// </summary> [ContextMenu("Create Mesh")] void EditorCreateMesh() { var randomMesh = target as RandomMesh; var meshFilter = randomMesh.GetComponent<MeshFilter>(); // 古い内蔵メッシュを削除 var meshAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(randomMesh)); foreach (var meshAsset in meshAssets) { if (meshAsset is Mesh) { Object.DestroyImmediate(meshAsset, true); } } // メッシュ作成 var newMesh = randomMesh.CreateNewMesh(); newMesh.name = k_ExportMeshName; meshFilter.sharedMesh = newMesh; // メッシュを内蔵させる AssetDatabase.AddObjectToAsset(newMesh, randomMesh); randomMesh.OnCreateText = string.Format( "【現在のメッシュ情報】\n・雨の粒の数:{0}\n・雨の粒の大きさ:{1}\n・雨全体の大きさ: {2}", randomMesh.TriangleCount, randomMesh.TriangleScale, randomMesh.TriangleRange ); // 保存 AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } /// <summary> /// メッシュの保存パスを生成(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; // アセットの保存先パス return assetPath; } }
以上で2つのC#スクリプトの作成は完了です。
実際にメッシュを作ってみる
次に、三角形メッシュを実際に作ってみます。
Rainオブジェクトの作成
HierarchyウィンドウでGameObjectを作成します.
オブジェクトの名前をRainにします.
コンポーネントRandomMeshをくっつける
RainオブジェクトにRandomMeshコンポーネントを追加します。
コンポーネントを追加するとInspectorが以下のような表示になります
RainオブジェクトをPrefab化する
次にRainオブジェクトをPrefab化します。 HierarchyウィンドウのRainオブジェクトをProjectウィンドウへドラッグ&ドロップします
Prefabが作成されます。
メッシュ作成
RainのPrefabを選択した状態でInspectorウィンドウ上の「メッシュの更新」ボタンをクリックします。
三角形メッシュがたくさん表示されます。
メッシュがピンク色になる原因
メッシュの色がピンク色になっていますが、これはRainオブジェクトのMeshRendererに マテリアルが登録されていないことが原因です。
マテリアルを登録することで色味を調整することができるようになります。
MeshRenderにマテリアルを登録する
MeshRendererへマテリアルを登録する手順を解説します。 MeshRendererのMaterialsの部分をクリックします。
Materialsの丸ポチの部分をクリックすると、マテリアル一覧ウィンドウが表示されるので 登録したいマテリアルを選択します。
Default-Diffuseを選択するとDefault-DiffuseマテリアルがMeshRendererに登録されます。
Default-Diffuseマテリアルを登録した場合、白色になります。
三角形メッシュに動きを与える
次にメッシュに動きを与えることでより雨らしくなります。 ここでは、三角形メッシュに動きを与える手順を解説します。
カスタムシェーダーで動きを作る
今回は、カスタムシェーダーを利用して頂点を動かし、雨っぽい動きを与えます。
カスタムシェーダーの作成
ここからは実際にカスタムシェーダーを作成する手順を解説します。
まずはProjectウィンドウのCreateをクリックします。(Projectウィンドウ上での右クリックでもOK)
Shader/Standard Surface Shaderを選択します。
シェーダが出現するので、名前をRainにします。
シェーダーファイルの編集
シェーダーRainを開きます。
シェーダーRain.shaderを以下のように書き換えます。
Shader "Custom/Rain" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _Speed ("[VS]雨が落ちる速さ", Float) = 6.0 _Scale ("[VS]雨の高さ", Float) = 4.0 _Remap("[VS]Remap", Range(0.0, 1.0)) = 0.7 [Space] _Albedo ("[FS]雨 色", Color) = (1.0, 1.0, 1.0, 0.5) _Emission ("[FS]雨 発光色", Color) = (0.0, 0.0, 0.0, 0.0) _Specular ("[FS]雨 スペキュラーパワー", Range(0.0, 1.0)) = 0.5 _Gloss ("[FS]雨 スペキュラー強度", Range(0.0, 1.0)) = 0.5 } SubShader { Tags { "Queue" = "Transparent" "RenderType" = "Transparent" } CGPROGRAM #pragma surface surf Lambert alpha #pragma vertex vert sampler2D _MainTex; // [0;1]のランダムな値を返す関数 float nhash11(float n){ return frac(sin(n) * 43758.5453); } // 値域[a;b] を 値域[0;1]へ変換する関数 float remap(float t, float a, float b){ return clamp((t-a)/(b-a), 0, 1); } // 頂点シェーダー half _Speed; half _Scale; half _Range; fixed _Remap; // 色 half4 _Albedo; half4 _Emission; fixed _Specular; fixed _Gloss; // 頂点シェーダー関数 void vert(inout appdata_full v) { fixed rnd = nhash11(fmod(v.vertex.z, 512.0)); // ランダム値 //float timer = _Time.w * _Speed * remap(0.7, 1.0, rnd); float timer = _Time.w * _Speed * remap(_Remap, 1.0, rnd); // 値域の変換 [_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; }; // サーフェースシェーダー関数 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; } ENDCG } }
以上でシェーダーの編集は完了となります。
補足: シェーダーのファイル名について
Unity上でのシェーダーの名前表示はRainですが、実際のファイル名はRain.shaderになります。
Projectウィンドウの下を見るとファイル名を確認できます。
マテリアルの作成
次にマテリアルを作成するまでの手順を解説します。
シェーダーRainを右クリックし、Create/Materialを選択します。
Custom_Rainという名前のマテリアルが作成されます
以上で頂点を揺らすためのファイル作成は完了となります
マテリアルを試しに使ってみる
作成したマテリアルCustom_Rainを、シーン上の適当な3Dモデルにくっつけてみまっしょう
3Dモデルにマテリアルをくっつけると以下のような動きになります。
マテリアルCustom_Rainはモデルの頂点を動かしているため、このようなゆらゆらとした動きになります。
マテリアルの設定の確認
マテリアルをクリックすると、Inspectorウィンドウにマテリアルの設定数値が表示されます。
ここにある数値を変更することで、マテリアルの挙動を変えることができます。
雨に動きを与える
マテリアルCustom_RainをRainオブジェクトにくっつけると、雨のような動きをするようになります。
ここでは、三角形メッシュにマテリアルをくっつけて動きをつける手順を解説します。 まずは雨のPrefabを選択し、Materialsの右にある〇ポチをクリックします。
マテリアル一覧の中から先ほど作成したマテリアルCustom_Rainを選択します。
マテリアルCustom_Rainを設定すると動きが与えられて雨のような動きをするようになります。
雨の見た目の調整
雨の太さや色を調整して、より雨らしい見た目へと調整していきます。 まずはマテリアルCustom_Rainを選択し、色の入力欄をクリックします。
色のウィンドウが出てくるので、 以下のように設定し、雨を青っぽい半透明な色にします
設定すると以下のような見た目になります。
形の調整(雨粒の大きさや数など)
雨のPrefabの設定を変更することで、雨粒の大きさや雨粒の数などを変更することができます。
雨粒を小さくしてみる
雨粒の大きさの部分の数値を変えると雨粒の大きさを変えることができます。
大きさを0.1にした場合、雨は以下のような見た目になります。
雨の数を増やしてみる
雨粒の数を増やすと、濃い雨になります。
雨粒の数を6000に設定すると、以下のような見た目になります。
雨をバラつかせてみる
雨全体のバラつきを増やすと雨がバラつくようになります。
雨全体のバラつきに(16,4,16)を設定すると、以下のような見た目になります。
STYLYへアップロード
雨のPrefabを右クリックし、「Upload prefab to STYLY」を選択。
アップロードが始まるので、気長に待ちます。 Upload Succeededと出ればアップロード完了です。
STYLY上でMyModelsの中を見ると、アップロードしたRainがあります。
STYLYに雨を降らせましょう
※サンプルプロジェクトはこちらから:https://github.com/styly-dev/STYLY-Unity-Examples/tree/master/Assets/STYLY_Examples/Rain