Страница 1 из 1

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

СообщениеДобавлено: 06 май 2017, 09:23
Valentinus
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" нежелательны

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

СообщениеДобавлено: 06 май 2017, 09:53
samana
Синтаксис:
Используется csharp
 if ( hand=null)

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

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

СообщениеДобавлено: 06 май 2017, 14:23
Valentinus
samana писал(а):
Синтаксис:
Используется csharp
 if ( hand=null)

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


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

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

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

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


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

upd^ пост поправил, см. далее

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

СообщениеДобавлено: 06 май 2017, 16:22
samana
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.

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

СообщениеДобавлено: 06 май 2017, 17:05
DbIMok
непонятно зачем так велосипедить. Find нормально ищет по полному пути в иерархии через /

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

СообщениеДобавлено: 06 май 2017, 17:09
Valentinus
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 подключится ко всем моим трансформам.

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

СообщениеДобавлено: 06 май 2017, 17:11
Valentinus
DbIMok писал(а):непонятно зачем так велосипедить. Find нормально ищет по полному пути в иерархии через /


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

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

СообщениеДобавлено: 06 май 2017, 17:25
samana
DbIMok писал(а):непонятно зачем так велосипедить. Find нормально ищет по полному пути в иерархии через /

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

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

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

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

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

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

СообщениеДобавлено: 06 май 2017, 17:29
Valentinus
samana писал(а): видимо очень накладным оказалось прописывать весь путь к конкретному объекту, возможно там десяток имён, которые даже просто лень перепечатывать)

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


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


спасибо, все понял.

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

СообщениеДобавлено: 06 май 2017, 17:38
samana
Valentinus писал(а):странно что в инспекторе и сцене нет способа скопипастить полный путь к GO

Но если что, то можно немного расширить редактор и добавить такую фишку. Unity старается предоставить почти любой пользовательский каприз, вот только писать придётся самим.

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

СообщениеДобавлено: 06 май 2017, 18:16
samana
Если вам всё таки интересно о том, как добавить фишку с нахождением всего пути к объекту, то это делается примерно так.
Создаёте показанный скрипт. Заносите его в папку 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("Сначала нужно выделить объект в иерархии.");
    }

}
 

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

СообщениеДобавлено: 06 май 2017, 19:12
Valentinus
samana писал(а):Если вам всё таки интересно о том, как добавить фишку с нахождением всего пути к объекту, то это делается примерно так.


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

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

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

СообщениеДобавлено: 08 май 2017, 18:06
samana
Valentinus писал(а):PS вместо names.Add(t.name); можно написать names.Insert(0,t.name); тогда реверс делать будет не нужно

Можно даже вообще обойтись без массива и сразу собирать строку :)