初めに
Hierarchy内の指定のコンポーネントを全部取得して
取得したものに何かの処理を一気にかけたい
例:私の場合は
Hierarchyに無いあるSkinnedMeshRendererの
Cast shadowのモードを一気に変更したいでした。
単純に全部取得として、リストにするのではなく、各rootのオブジェクト事に
listにまとめたいということで、スクリプトを書いてみました。
スクリプト
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
namespace hoge
{
[System.Serializable]
public class ObjectList<T> where T : class
{
/// <summary>
/// root name
/// </summary>
public string rootObjectName;
/// <summary>
/// root Object
/// </summary>
public GameObject rootObject;
/// <summary>
/// root オブジェクト以下のオブジェクトのlistが入る
/// </summary>
[SerializeField]
public List<FoundObject<T>> roundObjectList;
}
[System.Serializable]
public class FoundObject<T> where T : class
{
/// <summary>
/// Object name
/// </summary>
public string ObjectName;
/// <summary>
/// オブジェクト
/// </summary>
public T Object;
}
[System.Serializable]
public class FindObjectsToList<T> where T : UnityEngine.Object
{
[SerializeField]
private bool _exclusionRootObject = false;
/// <summary>
/// 検索するオブジェクトにrootのオブジェクトを含むか含めないか
/// </summary>
public bool exclusionRootObject
{
set { _exclusionRootObject = value; }
}
[SerializeField]
private List<ObjectList<T>> _objectList = new List<ObjectList<T>>();
/// <summary>
/// Searchして見つけたオブジェクトの取得
/// </summary>
public List<ObjectList<T>> objectList
{
get { return _objectList; }
}
/// <summary>
/// オブジェクトのサーチ
/// </summary>
public void Search()
{
Clear();
// var findObj = GameObject.FindObjectsOfType<T>();
var findObj = GameObject.FindObjectsOfType<Transform>();
foreach (var obj in findObj)
{
var gameObj = obj;
//var gameObj = obj as GameObject; // nullになる。。
// generics で型取得
var comp = gameObj.GetComponent<T>();
// 取得出来たか判定
if (comp == null)
{
continue;
}
ObjectList<T> root = new ObjectList<T>();
root.rootObjectName = gameObj.transform.root.name;
root.rootObject = gameObj.transform.root.gameObject;
root.roundObjectList = new List<FoundObject<T>>();
// rootのオブジェクトの名前を元にlist組むので名前検索
var find = _objectList.Where(_ => _.rootObjectName == root.rootObjectName);
// 一つも無かったらrootとして登録
if (find.Count<ObjectList<T>>() == 0)
{
_objectList.Add(root);
}
FoundObject<T> fObj = new FoundObject<T>();
// rootのオブジェクトをlistに登録するか判定
bool exclusion = (_exclusionRootObject == true ? root.rootObjectName != gameObj.name : true);
if (exclusion)
{
fObj.ObjectName = gameObj.name;
fObj.Object = comp;
// rootが見つかった最初のオブジェクトに見つかったオブジェクト追加していく
find.First<ObjectList<T>>().roundObjectList.Add(fObj);
}
}
}
/// <summary>
/// listのクリア
/// </summary>
private void Clear()
{
if (_objectList != null)
{
for (var i = 0; i < _objectList.Count; i++)
{
_objectList[i].rootObjectName = "";
_objectList[i].rootObject = null;
if (_objectList[i].roundObjectList != null)
{
for (var j = 0; j < _objectList[i].roundObjectList.Count; j++)
{
_objectList[i].roundObjectList.Clear();
}
_objectList[i].roundObjectList = null;
}
}
_objectList.Clear();
}
}
}
}
結果から言うと、出来たが自分が思い描いた通りにはなりませんでした。
思い通りにいかなかった点
※1の部分
抜粋するとGameObject.FindObjectsOfTypeで取得したかった
コンポーネントがジェネリック型で取得したかった
※2の部分
取得したオブジェクトをGameObjectにキャスト
しかし、取得してもnullになる。。
※3の部分
GameObjectにキャストしたかったのはrootをしらべたかった
// var findObj = GameObject.FindObjectsOfType<T>(); //※1
var findObj = GameObject.FindObjectsOfType<Transform>();
foreach (var obj in findObj)
{
var gameObj = obj;
//var gameObj = obj as GameObject; // ※2 nullになる。。
// generics で型取得
var comp = gameObj.GetComponent<T>();
// 取得出来たか判定
if (comp == null)
{
continue;
}
ObjectList<T> root = new ObjectList<T>();
// ※3
root.rootObjectName = gameObj.transform.root.name;
root.rootObject = gameObj.transform.root.gameObject;
一応、やりたかった事はできるがGameObject.FindObjectsOfType()
としてしまうことで、全オブジェクトを拾ってしまう。。
サンプル
using System.Collections;
using UnityEngine;
using hoge;
public class TestClass : MonoBehaviour
{
public FindObjectsToList<Transform> find;
private void Search()
{
find.Search();
}
// Start is called before the first frame update
void Start()
{
Search();
}
}
とりあえず。うまくいったがあんまり、納得いってない。。
最後に
もっといい方法を知っている方がいましたら、教えてください。
↧