プロジェクト内の全てのシーンに含まれている、特定の型の全コンポーネントに対して何らかの処理を行う方法です。
想定される利用例
様々な用途が考えられますが、パッと思いついたものをいくつか書いておきます。
- 全てのTextMeshProUGUIに対して、特定のFontAssetを指定する
- 全てのTextに対して、TextMeshProUGUIに置き換える
- 全てのImageに対して、RaycastTargetを無効にする
- 全てのCameraに対して、Backgroundを変更する
- 全てのGameObjectに対して、アクティブ状態にする
ソースコード
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ComponentSearcher : MonoBehaviour
{
/// <summary>
/// メニューバーから実行できるようにする
/// Tools > ProcessAllComponents
/// </summary>
[MenuItem("Tools/ProcessComponentsInAllScenes")]
private static void ProcessComponentsInAllScenes()
{
// 例: SpriteRendererを対象にする
ProcessComponentsInAllScenes<SpriteRenderer>();
}
/// <summary>
/// 全コンポーネントに対して行う処理
/// </summary>
/// <param name="component">対象のコンポーネント</param>
/// <typeparam name="T">対象のコンポーネント型</typeparam>
private static void MyAction<T>(T component)
{
var spriteRenderer = component as SpriteRenderer;
if(spriteRenderer == null) return;
// 例: 全SpriteRendererのcolorをログ出力
Debug.Log(spriteRenderer.color);
}
/// <summary>
/// 全シーン内にあるコンポーネントに対してMyActionを行う
/// </summary>
/// <typeparam name="T">対象のコンポーネント型</typeparam>
private static void ProcessComponentsInAllScenes<T>()
{
var dirInfo = new DirectoryInfo(Application.dataPath);
var sceneFiles = dirInfo.GetFiles("*.unity", SearchOption.AllDirectories).ToList();
var currentOpenScenePath = EditorSceneManager.GetActiveScene().path;
var components = new List<T>();
foreach (var sceneFile in sceneFiles)
{
var splitedScenePath = sceneFile.FullName.Split(new char['/']);
var scenePath = splitedScenePath[splitedScenePath.Length - 1];
var scene = EditorSceneManager.OpenScene(scenePath);
var componentsInScene = GetComponentsInScene<T>(scene);
foreach (var component in componentsInScene)
{
MyAction<T>(component);
}
components.AddRange(componentsInScene);
}
EditorSceneManager.OpenScene(currentOpenScenePath);
}
/// <summary>
/// 1つのScene内にある特定のコンポーネントを全て取得
/// </summary>
/// <param name="scene">対象のScene</param>
/// <typeparam name="T">コンポーネント型</typeparam>
/// <returns>Scene内にある全コンポーネントのリスト</returns>
private static List<T> GetComponentsInScene<T>(Scene scene)
{
var rootGameObjects = scene.GetRootGameObjects();
var list = new List<T>();
foreach (var root in rootGameObjects)
{
var components = root.GetComponentsInChildren<T>(true);
list.AddRange(components);
}
return list;
}
}
コメントで「例: 〜〜〜」と書いてある部分を適宜修正して、UnityエディタのメニューバーからTools > ProcessAllComponents
を選択すれば、全コンポーネントに対してMyActionメソッド
を実行します。
sceneFilesを取得する部分を工夫すれば、特定のフォルダ直下にあるシーンのみを対象にしたりも可能です。
注意点としては、Editorスクリプトを使っているのと、「全シーンを1つずつ開いて処理して閉じるのを繰り返す」ということをしているので、PlayMode時(エディタ実行中)には使えません。
コメント