C# を使用して、Unity3D で非アクティブなオブジェクトを見つける必要がありました。
64 個のオブジェクトがあり、ボタンをクリックすると、実行時に対応するボタンのオブジェクトがアクティブ化/非アクティブ化されます。現時点で非アクティブなオブジェクトを見つけるにはどうすればよいですか?
まあ、 usingGameObject.Find(...)
は非アクティブなオブジェクトを返すことはありません。ドキュメントに記載されているように:
この関数はアクティブなゲームオブジェクトのみを返します。
できたとしても、これらのコストのかかる通話を最小限に抑えたいと思うでしょう。
呼び出しを使用するなど、非アクティブなゲームオブジェクトを見つけるための「トリック」がありResources.FindObjectsOfTypeAll(Type type)
ます (ただし、これは細心の注意を払って使用する必要があります)。
ただし、最善の策は、独自の管理コードを作成することです。これは、ある時点で見つけて使用する可能性のあるオブジェクトのリストを保持する単純なクラスにすることができます。最初のロード時にオブジェクトを入れることができます。または、アクティブまたは非アクティブになったときにそれらを追加/削除することもできます。特定のシナリオが必要とするものは何でも。
この質問が出されてから数年、Unity はまさにあなたが必要としているものを提供してくれました。少なくとも、まさに私が必要としていたもの。未来の人々のためにここに投稿します。
アクティブまたは非アクティブなゲームオブジェクト上にある特定のタイプのオブジェクトを見つけるには、次を使用できます。FindObjectsOfType<T>(true)
非アクティブなゲームオブジェクトにアタッチされたオブジェクトは、
inactiveObjects
が に設定されている場合にのみ含まれtrue
ます。
したがって、通常のように使用するだけでなく、 も渡しtrue
ます。
次のコードには次が必要System.Linq
です。
SpriteRenderer[] onlyActive = GameObject.FindObjectsOfType<SpriteRenderer>();
SpriteRenderer[] activeAndInactive = GameObject.FindObjectsOfType<SpriteRenderer>(true);
// requires "using System.Linq;"
SpriteRenderer[] onlyInactive = GameObject.FindObjectsOfType<SpriteRenderer>(true).Where(sr => !sr.gameObject.activeInHierarchy).ToArray();
最初の配列にはアクティブなゲームオブジェクトの SpriteRenderer のみが含まれ、2 番目の配列にはアクティブなゲームオブジェクトと非アクティブなゲームオブジェクトの両方が含まれ、3 番目の配列は非アクティブなゲームオブジェクトの SpriteRendererSystem.Linq
のみが含まれます。
親オブジェクト (フォルダーの役割を果たす空のオブジェクト) がある場合、次のようにアクティブなオブジェクトと非アクティブなオブジェクトを見つけることができます。
this.playButton = MainMenuItems.transform.Find("PlayButton").gameObject;
MainMenuItems - 親オブジェクトです。
Find() は遅いメソッドなので、オブジェクトへの参照を使用するか、非常に頻繁にアクセスする必要があるゲームオブジェクトで辞書コレクションを整理することを検討してください。
幸運を!
述語を使用できます。以下のように、gameObjects を取得し、Predicate でチェックするだけです。
public List<GameObject> FindInactiveGameObjects()
{
GameObject[] all = GameObject.FindObjectsOfType<GameObject> ();//Get all of them in the scene
List<GameObject> objs = new List<GameObject> ();
foreach(GameObject obj in all) //Create a list
{
objs.Add(obj);
}
Predicate inactiveFinder = new Predicate((GameObject go) => {return !go.activeInHierarchy;});//Create the Finder
List<GameObject> results = objs.FindAll (inactiveFinder);//And find inactive ones
return results;
}
システムを使用する ことを忘れないでください。System.Collections.Generic の使用;
正解ではありませんが、これが私の場合のやり方です。
1) スクリプトを (非アクティブな) ゲーム オブジェクトにアタッチし、設定してから非アクティブにするのではなく、アクティブのままにします。
2) シーンの外に配置します。
3) スクリプトに非アクティブを示すフラグを設定します。
4) Update() で、この非アクティブ フラグをチェックし、false の場合は関数呼び出しをスキップします。
5) オブジェクトが必要な場合は、適切な場所に配置し、フラグをアクティブに設定します。
少しパフォーマンスの問題になりますが、これが今のところ考えられる唯一の回避策です。