夜景のビルの窓にランダムでマテリアルを割り当てました。
スクリプト
Editorフォルダーに新規C#スクリプトを作成します。
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
public class RandomMaterialSetter : EditorWindow
{
private List<Material> materials = new List<Material>();
string objTag;
float emissiveWindowRate;
[MenuItem("Window/Random Material Setter")]
public static void ShowWindow()
{
GetWindow("Random Material Setter");
}
private void OnGUI()
{
// テキストフィールドを表示
objTag = EditorGUILayout.TextField("Tag",objTag);
// マテリアルをアタッチする欄を表示
for (int i = 0; i < materials.Count; i++)
{
materials[i] = (Material)EditorGUILayout.ObjectField(materials[i], typeof(Material), true);
}
// スライダーを表示
using (var h = new EditorGUILayout.HorizontalScope("Slider", GUILayout.Height(10f)))
{
EditorGUILayout.LabelField("Emissive Window Rate", GUILayout.Width(150f));
emissiveWindowRate = Mathf.Round(EditorGUILayout.Slider(emissiveWindowRate, 0f, 1f) * 100f) / 100f;
}
// 追加ボタン
if (GUILayout.Button("Add Material Slot"))
{
materials.Add(null);
}
// 除去ボタン
if (GUILayout.Button("Remove Material Slot"))
{
if (materials.Count > 0)
{
materials.RemoveAt(materials.Count - 1);
}
}
// フィールド数を表示
if (materials != null)
{
GUILayout.Label(materials.Count + "");
}
// ランダムで適用
if (GUILayout.Button("Apply Random Material"))
{
ApplyRandomMaterial();
}
}
private void ApplyRandomMaterial()
{
// マテリアルがなければ終了
if (materials.Count == 0)
{
Debug.LogWarning("No materials set in Random Material Setter.");
return;
}
// nullでないマテリアルのリストを作る
List<Material> nonNullMaterials = new List<Material>();
foreach(var m in materials)
{
if(m != null)
{
nonNullMaterials.Add(m);
}
}
if (nonNullMaterials.Count == 0) return;
// 確率に基づいてマテリアルリストを調整
var adjustedList = AdjustMaterialList(nonNullMaterials, emissiveWindowRate, 100);
foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[])
{
// ヒエラルキーにあるゲームオブジェクト
if (!EditorUtility.IsPersistent(go.transform.root.gameObject) && !(go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave))
{
if (go.tag != objTag) continue;
var r = go.GetComponent<MeshRenderer>();
if (r == null) continue;
Undo.RecordObject(r, "Set Random Material to " + go.name);
// ランダムでマテリアルを選択
var randomMaterial = adjustedList[Random.Range(0, adjustedList.Count)];
if (randomMaterial == null)
{
// nullのときレンダラーを無効化
r.enabled = false;
}
else
{
// レンダラーを有効化してマテリアルを設定
r.enabled = true;
r.sharedMaterial = randomMaterial;
}
}
}
}
public static List<Material> AdjustMaterialList(List<Material> availableMaterials, float probability, int listSize = 100)
{
List<Material> adjustedList = new List<Material>();
// リストサイズに確率を掛ける
int litMaterialCount = Mathf.RoundToInt(listSize * probability);
// リストに光るマテリアルを追加
for (int i = 0; i < litMaterialCount; i++)
{
// ランダムにマテリアルを選択するか、何らかの方法で決定
//Material selectedMaterial = availableMaterials[Random.Range(0, availableMaterials.Count)];
Material selectedMaterial = availableMaterials[i % availableMaterials.Count];
adjustedList.Add(selectedMaterial);
}
// 残りのスペースにはnullを追加
for (int i = litMaterialCount; i < listSize; i++)
{
adjustedList.Add(null);
}
return adjustedList;
}
}
シーンを設定
ビルの窓に合わせてPlaneが配置されています。
窓には専用のタグが設定されています。
エディタウィンドウに複数の窓マテリアルをアタッチします。追加ボタンでフィールドが増えます。スライダーで光る窓の出現率を設定できます。対象オブジェクトのタグを入力します。
適用ボタンで窓にマテリアルが割り当てられます。
窓にバリエーションがついて自然に見えるようになりました。