Unity как найти неактивный объект на сцене

В сцене есть неактивный элемент. Как его найти программно ? Я пробовал искать по тегу просто искать возвращает null как будто его и нету.

GameObject go1 = GameObject.FindGameObjectsWithTag("tag");  // null
GameObject go2 = GameObject.Find("P_Complete");             // null

введите сюда описание изображения

задан 17 фев 2019 в 12:05

Madoka Magica's user avatar

GameObject.Find

Finds a GameObject by name and returns it.

This function only returns active GameObjects. If no GameObject with
name can be found, null is returned. If name contains a ‘/’ character,
it traverses the hierarchy like a path name.


public static class GameObjectExtension {
    public static Object Find(string name, System.Type type) {
        Object[] objects = Resources.FindObjectsOfTypeAll(type);
        foreach(var obj in objects) {
            if(obj.name == name) {
                return obj;
            }
        }
        return null;
    }

    public static GameObject Find(string name) {
        return Find(name, typeof(GameObject)) as GameObject;
    }
}

Использование:

void TestMethod() {
    GameObject obj = GameObjectExtension.Find("GameObject");
    if (obj) {
        obj.SetActive(true);
    }
}

P.S.

Данный подход очень, очень и еще раз очень медленный. Использовать его нужно только в самых крайних случаях. Сама проблема поиска неактивных объектов зачастую возникает из-за неправильной архитектуры, такие проблемы обычно решаются через ручную установку референсов.

ответ дан 17 фев 2019 в 12:43

1

Эта функция возвращает любой объект Юнити, который загружен включая префабы, текстуры итд, в том числе и отключенные геймобджекты

Resources.FindObjectsOfTypeAll<T>()

ответ дан 17 фев 2019 в 12:35

Stranger in the Q's user avatar

Stranger in the QStranger in the Q

56k10 золотых знаков79 серебряных знаков133 бронзовых знака

For newer Unity versions this answer provides probably a better solution!


First of all

In general any usage of Find or it’s variants should be avoided.

Actually they are never really required but only a “hot-fix” used to cover an implementation “laziness”.

Usually from the beginning storing and passing on required references is always the better approach.

Especially in your case you seem to have a fix amount of objects so you could probably already reference them all in a certain “manager” component and store them in a list or array (them you can get a reference by index) or even a Dictionary<string, GameObject> (then you can also get the according reference by name – you can find an example below).


Workarounds

There are alternative solutions (FindObjectsWithTag, FindObjectsOfType) but it will always be quite expensive (though most of the Find variants are expensive anyway).

You could e.g. also “manually” iterate through all objects in the scene using Scene.GetRootGameObjects

Returns all the root game objects in the Scene.

And then search through them until you find your object. This way you get also inactive GameObject.

public static GameObject Find(string search)
{
    var scene = SceneManager.GetActiveScene();
    var sceneRoots = scene.GetRootGameObjects();

    GameObject result = null;
    foreach(var root in sceneRoots)
    {
        if(root.name.Equals(search)) return root;

        result = FindRecursive(root, search);

        if(result) break;
    }

    return result;
}

private static GameObject FindRecursive(GameObject obj, string search)
{
    GameObject result = null;
    foreach(Transform child in obj.transform)
    {
        if(child.name.Equals(search)) return child.gameObject;

        result = FindRecursive (child.gameObject, search);

        if(result) break;
    }

    return result;
}

But ofcourse this should be strongly avoided and the usage of such deep searches reduced to a minimum!


What I would do

Another way – in my eyes the best approach here – could be to have a certain component attached to all your objects and actually store all the references once as said before in a dictionary like e.g.

public class FindAble : MonoBehaviour
{
    private static readonly Dictionary<string, GameObject> _findAbles = new Dictionary<string, GameObject>();

    public static GameObject Find(string search)
    {
        if(!_findAbles.ContainsKey(search)) return null;

        return _findAbles[search];
    }

    private IEnumerator Start()
    {
        // Wait one frame
        // This makes it possible to spawn this object and 
        // assign it a different name before it registers
        // itself in the dictionary
        yield return null;

        if(_findAbles.ContainsKey(name))
        {
            Debug.LogError($"Another object with name /"{name}/" is already registered!", this);
            yield break;
        }

        _findAbles.Add(name, gameObject);
    }

    private void OnDestroy ()
    {
        if(_findAbles.ContainsKey(name))
        {
            _findAbles.Remove(name);
        }

        // Optionally clean up and remove entries that are invalid
        _findAbles = _findAbles.Where(kvp => kvp.Value).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
    }
}

and then use it like

var obj = FindAble.Find("SomeName");
if(obj)
{
    // ...
}

Also for this the component would need to be enabled at least once so Start is called.

Again an alternative would be to have instead a

public void Initialize(string newName)
{
    if(_findAbles.ContainsKey(name))
    {
        Debug.LogError($"Another object with name /"{name}/" is already registered!", this);
        return;
    }

    name = newName;

    _findAbles.Add(name, gameObject);
}

which you could call also after e.g. spawning an inactive object.

Как найти выключенный объект на сцене и включить?

Как найти выключенный объект на сцене и включить?

Собственно, тема раскрыта в названии. Создан private GameObject и внутри класса я должен его найти и включить. Скрин прилагается
Изображение

pesiik
UNITрон
 
Сообщения: 223
Зарегистрирован: 01 авг 2015, 11:46

Re: Как найти выключенный объект на сцене и включить?

Сообщение GeoGraf 07 окт 2015, 16:42

Насколько я знаю найти выключенный объект невозможно.
Если Вы его создаете программно, то перед выключением сохраните на него ссылку.
Если он должен быть на сцене изначально, то сделайте его активным, а при старте сохраните ссылку и выключите его.

Аватара пользователя
GeoGraf
UNITрон
 
Сообщения: 341
Зарегистрирован: 10 сен 2014, 16:53
Откуда: Тверь, Россия

Re: Как найти выключенный объект на сцене и включить?

Сообщение pesiik 07 окт 2015, 16:47

GeoGraf писал(а):Насколько я знаю найти выключенный объект невозможно.
Если Вы его создаете программно, то перед выключением сохраните на него ссылку.
Если он должен быть на сцене изначально, то сделайте его активным, а при старте сохраните ссылку и выключите его.

Это понятно. дело в том, что у меня около 300 объектов в одной точке. и мне надо включать камеру и один из объектов по нажатию ui кнопки. эт придется все 300 объектов прописывать))) че т не крут. мож есть способ?

pesiik
UNITрон
 
Сообщения: 223
Зарегистрирован: 01 авг 2015, 11:46

Re: Как найти выключенный объект на сцене и включить?

Сообщение GeoGraf 07 окт 2015, 16:58

Если объект удочерен, тогда так:
Метод:

Используется csharp

public static GameObject FindObject(this GameObject parent, string name)
 {
     Transform[] trs= parent.GetComponentsInChildren(typeof(Transform), true);
     foreach(Transform t in trs){
         if(t.name == name){
              return t.gameObject;
         }
     }
     return null;
 }

Использование метода:

Используется csharp

GameObject obj = parentObject.FindObject(“MyObject”);

Аватара пользователя
GeoGraf
UNITрон
 
Сообщения: 341
Зарегистрирован: 10 сен 2014, 16:53
Откуда: Тверь, Россия

Re: Как найти выключенный объект на сцене и включить?

Сообщение pesiik 07 окт 2015, 17:09

GeoGraf писал(а):Если объект удочерен, тогда так:
Метод:

Используется csharp

public static GameObject FindObject(this GameObject parent, string name)
 {
     Transform[] trs= parent.GetComponentsInChildren(typeof(Transform), true);
     foreach(Transform t in trs){
         if(t.name == name){
              return t.gameObject;
         }
     }
     return null;
 }

Использование метода:

Используется csharp

GameObject obj = parentObject.FindObject(“MyObject”);

Ооо спасибо! возьму на вооружение. Но я другой хитростью воспользовался. Просто все объекты включил и вынес за пределы камеры. И определенный перемещается в центр камеры. А скрпит обзора повесил на пустой объект в центре камеры

pesiik
UNITрон
 
Сообщения: 223
Зарегистрирован: 01 авг 2015, 11:46

Re: Как найти выключенный объект на сцене и включить?

Сообщение Linebeck 08 окт 2015, 08:54

pesiik писал(а):Собственно, тема раскрыта в названии. Создан private GameObject и внутри класса я должен его найти и включить. Скрин прилагается
Изображение

Объект включить нельзя. Зато можно компонет объекта включить/выключить, renderer например.

Аватара пользователя
Linebeck
UNец
 
Сообщения: 48
Зарегистрирован: 08 июн 2015, 09:49



Re: Как найти выключенный объект на сцене и включить?

Сообщение Zaicheg 09 окт 2015, 00:12

Linebeck писал(а):

Выключает объект.

У меня такая же проблема дома: выключатели света есть, а включателей нет. Я сдуру половину ламп выключил, что теперь делать — не знаю.

Аватара пользователя
Zaicheg
Адепт
 
Сообщения: 3024
Зарегистрирован: 19 июн 2009, 15:12
Откуда: Череповец

Re: Как найти выключенный объект на сцене и включить?

Сообщение Vrz 09 окт 2015, 17:10

Linebeck писал(а):

Выключает объект.

false меняешь на true и он включается, у меня никаких проблем с этим нет.

Что касается первого поста, то вместо Instrument.gameObject.SetActive() должно быть Instrument.SetActive(true), на сколько я помню. И ещё надо проверить устанавливается ли объект вообще в Instrument (т.к. он запривачен, смотреть инспектор в режиме дебаг), а то ошибка в 25 строке подозрительна. При чём родительский объект тоже должен быть включён.

Vrz
UNец
 
Сообщения: 3
Зарегистрирован: 30 сен 2015, 15:18

Re: Как найти выключенный объект на сцене и включить?

Сообщение Linebeck 10 окт 2015, 01:21

Vrz писал(а):

Linebeck писал(а):

Выключает объект.

false меняешь на true и он включается, у меня никаких проблем с этим нет.

Что касается первого поста, то вместо Instrument.gameObject.SetActive() должно быть Instrument.SetActive(true), на сколько я помню. И ещё надо проверить устанавливается ли объект вообще в Instrument (т.к. он запривачен, смотреть инспектор в режиме дебаг), а то ошибка в 25 строке подозрительна. При чём родительский объект тоже должен быть включён.

Ясно ,спасибо. У меня не включало год назад, приходилось через renderer работать, может уже пофиксили.

Аватара пользователя
Linebeck
UNец
 
Сообщения: 48
Зарегистрирован: 08 июн 2015, 09:49


Вернуться в Почемучка

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 28



GameObject.Find

Finds a GameObject by name and returns it.

This function only returns active GameObjects. If no GameObject with
name can be found, null is returned. If name contains a ‘/’ character,
it traverses the hierarchy like a path name.


public static class GameObjectExtension {
    public static Object Find(string name, System.Type type) {
        Object[] objects = Resources.FindObjectsOfTypeAll(type);
        foreach(var obj in objects) {
            if(obj.name == name) {
                return obj;
            }
        }
        return null;
    }

    public static GameObject Find(string name) {
        return Find(name, typeof(GameObject)) as GameObject;
    }
}

Использование:

void TestMethod() {
    GameObject obj = GameObjectExtension.Find("GameObject");
    if (obj) {
        obj.SetActive(true);
    }
}

P.S.

Данный подход очень, очень и еще раз очень медленный. Использовать его нужно только в самых крайних случаях. Сама проблема поиска неактивных объектов зачастую возникает из-за неправильной архитектуры, такие проблемы обычно решаются через ручную установку референсов.

Uzist

Сын моей мамы

187 / 130 / 60

Регистрация: 09.05.2020

Сообщений: 679

1

Найти неактивный объект на сцене

29.04.2022, 20:48. Показов 787. Ответов 4

Метки unity (Все метки)


Студворк — интернет-сервис помощи студентам

Здравствуйте, есть VictoryPanel, которая с самого начала неактивная.И при выполнении условия VictoryPanel становилась активной.Если что объект удочерён

Пробовал так(взял с форума)

C#
1
2
3
4
5
6
7
8
   Object[] objects = Resources.FindObjectsOfTypeAll(type);
                foreach (var obj in objects)
                {
                    if (obj.name =="VictoryPanel")
                    {
                        obj.SetActive(true);
                    }
                }

но выдало ошибки : ‘Object’ is an ambiguous reference between ‘UnityEngine.Object’ and ‘object’
The name ‘type’ does not exist in the current context



0



vladpad92

18 / 11 / 7

Регистрация: 06.04.2022

Сообщений: 172

29.04.2022, 21:42

2

C#
1
2
public GameObject _obj; //кидаешь сюда в инспекторе панель
_obj.SetActive(true)

Добавлено через 46 секунд
Где и при каких условиях это писать решай сам



0



UnityNub

UNITY

75 / 48 / 28

Регистрация: 20.04.2022

Сообщений: 159

29.04.2022, 23:08

3

Лучший ответ Сообщение было отмечено Uzist как решение

Решение

Uzist, вам проще оставлять Panel активной, а скрывать компонент Image. тогда панель будет легко находиться.

C#
1
GetComponent<Image>().enabled = true;



1



Сын моей мамы

187 / 130 / 60

Регистрация: 09.05.2020

Сообщений: 679

29.04.2022, 23:35

 [ТС]

4

vladpad92, не, мне не подходит такой способ, раньше я им пользовался,тно сцен стало много и этот способ перестал мне подходить

Добавлено через 4 минуты
UnityNub, о, а вот это подойдёт.Ещё мне пришла в голову мысль на милисекунду с начала загрузки сцены оставлять панель активной и получать её в старте.Но надо будет посмотреть как это будет выглядеть



0



18 / 11 / 7

Регистрация: 06.04.2022

Сообщений: 172

30.04.2022, 09:58

5

Uzist, Тебе уже дали действенный способ, Убери галочку с Image в инспекторе, а потом включай через скрипт



0



Добавить комментарий