Instantiate не создает GO с родителем

Ошибки и баги Unity3D

Instantiate не создает GO с родителем

Сообщение Valentinus 06 май 2017, 09:23

Instantiate не создает GO с родителем

потребовалось динамически создавать объект из префаба, сразу с привязкой к другому объекту (оружие в руке).

Синтаксис:
Используется csharp
public void StayArmed()
                {
                        Transform hand = GM.Player.gobj.transform.FindChild ("mixamorig:RightHandMiddle1");
                        if ( hand=null)
                        {
                                print("!!! RightHandMiddle1 not found");
                                return;
                        }
                        GameObject model;
                        model = Resources.Load("Weapons/"+"Ak-47") as GameObject;
                        if (model == null )
                        {
                                print("!!! Resources.Load model failed: " + "Ak-47");
                                return;
                        }
                        active_weapon = Instantiate(model, hand);
                        print("ok, I`m armed");
                }


вот такая простая функция- в GO-игрока ищем его правую руку , загружаем нужный ресурс-модельку оружия, создаем ее экземпляр у руки.

в консоли вижу "ok, I`m armed", т.е. ошибок нет, и руку нашли, и модельку загрузили

но оружие создается не у руки, а у сцены :(

пробовал указывать другой parent, пробовал указывать третий параметр (true/false) - не помогает.
погуглил, нашел аналогичную проблему у чувака в 2013 году, решения прямого нет.
костыли типа "создать объект, указать родителя через parent" нежелательны
другое мое творчество: samlib.ru/u/us_w/
Аватара пользователя
Valentinus
Старожил
 
Сообщения: 889
Зарегистрирован: 24 мар 2017, 18:33

Re: Instantiate не создает GO с родителем

Сообщение samana 06 май 2017, 09:53

Синтаксис:
Используется csharp
 if ( hand=null)

А то, что вы приравниваете руку к null, может быть источником проблемы?
И работает ли метод FindChild корректно? А то я в справке такого не вижу, и двоеточие в качестве разделителя в иерархии выглядит странно, обычно пишут слеш.
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск

Re: Instantiate не создает GO с родителем

Сообщение Valentinus 06 май 2017, 14:23

samana писал(а):
Синтаксис:
Используется csharp
 if ( hand=null)

А то, что вы приравниваете руку к null, может быть источником проблемы?


ПОЗОР НА МОИ СЕДИНЫ!!!! 8() 8() 8()

"дело было не в бобине..." (с)

samana писал(а):
Синтаксис:
Используется csharp
 if ( hand=null)

И работает ли метод FindChild корректно? А то я в справке такого не вижу, и двоеточие в качестве разделителя в иерархии выглядит странно, обычно пишут слеш.


FindChild работает (v.5.5)
двоеточие тут не разделитель, а название меха (сгенерил его в Fuse/Mixamo).
причем первый узел находит, а вложенные в него - нет

upd^ пост поправил, см. далее
Последний раз редактировалось Valentinus 06 май 2017, 17:14, всего редактировалось 4 раз(а).
другое мое творчество: samlib.ru/u/us_w/
Аватара пользователя
Valentinus
Старожил
 
Сообщения: 889
Зарегистрирован: 24 мар 2017, 18:33

Re: Instantiate не создает GO с родителем

Сообщение samana 06 май 2017, 16:22

Valentinus писал(а):а модель дареная, мехи уже обозванные
блин, чо делать-то ...

Спокойствие, только спокойствие (с).
Видимо FindChild ищет детей только в первой ступени иерархии, а вам надо, чтобы поиск был по всем детям любой вложенности главного объекта. Для этого можно написать метод, который пройдёт рекурсией по всем-всем детям и попытается найти нужный по имени.

Создайте статический класс (не MonoBeh) в помощь, в котором будете писать методы расширения для трансформа. Например вот такой метод найдёт ребёнка по имени в любой вложенности.
Синтаксис:
Используется csharp
public static class TransformFindUtil
{
    public static Transform findChildByName(this Transform root, string name)
    {
        foreach (Transform child in root)
        {
            if (child.name == name) return child;
            else  return child.findChildByName(name);
        }
        return null;
    }
}


Теперь у любого вашего трансформа появился новый метод findChildByName.
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск

Re: Instantiate не создает GO с родителем

Сообщение DbIMok 06 май 2017, 17:05

непонятно зачем так велосипедить. Find нормально ищет по полному пути в иерархии через /
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05

Re: Instantiate не создает GO с родителем

Сообщение Valentinus 06 май 2017, 17:09

samana писал(а):
Спокойствие, только спокойствие (с).


да, дело оказалось не в двоеточии, а именно FindChild искал только детей, а внуков и далее - не искал.
я сделал по-старинке, дедовским способом:
Синтаксис:
Используется csharp
Transform DeepFindChild(Transform t, string name)
                {
                        Transform result = t.FindChild (name);
                        if (result != null)
                                return result;
                        foreach (Transform child in t)
                        {
                                result =  DeepFindChild (child , name);
                                if (result != null)
                                        return result;
                        }
                        return null;
                }
 


а не могли бы вы пояснить как использовать ваш код, куда его вставить? я не понимаю как TransformFindUtil подключится ко всем моим трансформам.
другое мое творчество: samlib.ru/u/us_w/
Аватара пользователя
Valentinus
Старожил
 
Сообщения: 889
Зарегистрирован: 24 мар 2017, 18:33

Re: Instantiate не создает GO с родителем

Сообщение Valentinus 06 май 2017, 17:11

DbIMok писал(а):непонятно зачем так велосипедить. Find нормально ищет по полному пути в иерархии через /


полный путь от корня сцены я конечно могу прописать, но лениво и не очень надежно (могу ошибиться) и недальновидно (вдруг придется менять).
Последний раз редактировалось Valentinus 06 май 2017, 17:39, всего редактировалось 3 раз(а).
другое мое творчество: samlib.ru/u/us_w/
Аватара пользователя
Valentinus
Старожил
 
Сообщения: 889
Зарегистрирован: 24 мар 2017, 18:33

Re: Instantiate не создает GO с родителем

Сообщение samana 06 май 2017, 17:25

DbIMok писал(а):непонятно зачем так велосипедить. Find нормально ищет по полному пути в иерархии через /

Да, я понимаю, но видимо очень накладным оказалось прописывать весь путь к конкретному объекту, возможно там десяток имён, которые даже просто лень перепечатывать)

Valentinus писал(а):я сделал по-старинке, дедовским способом:

Кажется ваш способ делает то же, что и мой метод.

Valentinus писал(а):а не могли бы вы пояснить как использовать ваш код, куда его вставить? я не понимаю как TransformFindUtil подключится ко всем моим трансформам.

Просто создаёте статический класс, который ничего не расширяет, в общем, как я и напечатал. Так как в этом классе есть метод расширения, то теперь у любого вашего трансформа в проекте, появится метод, который описан в этом классе. То-есть, как только вы в обычном класса MonoBeh-а напишите слово transform и поставите точку, то там появится так же метод findChildByName, как будто он был у трансформа по-умолчанию.
Просто почитайте про методы расширения в C#.
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск

Re: Instantiate не создает GO с родителем

Сообщение Valentinus 06 май 2017, 17:29

samana писал(а): видимо очень накладным оказалось прописывать весь путь к конкретному объекту, возможно там десяток имён, которые даже просто лень перепечатывать)

именно так. кстати, странно что в инспекторе и сцене нет способа скопипастить полный путь к GO


samana писал(а):
Просто создаёте статический класс, который ничего не расширяет, в общем, как я и напечатал. Так как в этом классе есть метод расширения, то теперь у любого вашего трансформа в проекте, появится метод, который описан в этом классе. То-есть, как только вы в обычном класса MonoBeh-а напишите слово transform и поставите точку, то там появится так же метод findChildByName, как будто он был у трансформа по-умолчанию.
Просто почитайте про методы расширения в C#.


спасибо, все понял.
другое мое творчество: samlib.ru/u/us_w/
Аватара пользователя
Valentinus
Старожил
 
Сообщения: 889
Зарегистрирован: 24 мар 2017, 18:33

Re: Instantiate не создает GO с родителем

Сообщение samana 06 май 2017, 17:38

Valentinus писал(а):странно что в инспекторе и сцене нет способа скопипастить полный путь к GO

Но если что, то можно немного расширить редактор и добавить такую фишку. Unity старается предоставить почти любой пользовательский каприз, вот только писать придётся самим.
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск

Re: Instantiate не создает GO с родителем

Сообщение samana 06 май 2017, 18:16

Если вам всё таки интересно о том, как добавить фишку с нахождением всего пути к объекту, то это делается примерно так.
Создаёте показанный скрипт. Заносите его в папку Editor, если такой папки нет, то создаёте её (этих папок может быть много в любых местах).
Теперь в верхнем меню Unity, появится новый пункт Samana (имя можете поменять конечно). Выделяете объект в иерархии и заходите в это меню Samana - CopyChildPath и у вас с буфер обмена скопируется полный путь к объекту, который можно потом вставить в ваш код.

Синтаксис:
Используется csharp
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class MyMenus
{
    [MenuItem("Samana/CopyChildPath")]
    private static void CopyFullPathOfSelectedChild()
    {
        // запоминаем выделенный объект
        Transform t = Selection.activeTransform;
        if (t != null)
        {
            // массив, куда будут заносится именя всех родителей
            List<string> names = new List<string>();

            // добавляем имена родителей в массив, до тех пор, пока родителей не станет
            while (true)
            {
                names.Add(t.name);
                t = t.parent;
                if (t == null) break;
            }

            // так как родители добавлялись с конца иерарации, то переворачиваем массив с именами, чтобы в начале оказался самый первый родитель и тд.
            names.Reverse();
            // формируем строку-путь вложенных объектов
            string result = names[0];
            for (int i = 1; i < names.Count; i++)
            {
                result += "/" + names[i];
            }

            // заносим путь в буфер обмена, чтобы в скрипте просто нажать CTRL+V
            Debug.Log(result);
            EditorGUIUtility.systemCopyBuffer = result;
        }
        else Debug.LogWarning("Сначала нужно выделить объект в иерархии.");
    }

}
 
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск

Re: Instantiate не создает GO с родителем

Сообщение Valentinus 06 май 2017, 19:12

samana писал(а):Если вам всё таки интересно о том, как добавить фишку с нахождением всего пути к объекту, то это делается примерно так.


спасибо! полезная штука.

PS вместо names.Add(t.name); можно написать names.Insert(0,t.name); тогда реверс делать будет не нужно :)
другое мое творчество: samlib.ru/u/us_w/
Аватара пользователя
Valentinus
Старожил
 
Сообщения: 889
Зарегистрирован: 24 мар 2017, 18:33

Re: Instantiate не создает GO с родителем

Сообщение samana 08 май 2017, 18:06

Valentinus писал(а):PS вместо names.Add(t.name); можно написать names.Insert(0,t.name); тогда реверс делать будет не нужно

Можно даже вообще обойтись без массива и сразу собирать строку :)
Аватара пользователя
samana
Адепт
 
Сообщения: 4738
Зарегистрирован: 21 фев 2015, 13:00
Откуда: Днепропетровск


Вернуться в Глюки

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1