Как я могу изменить родительский объект GameObject, созданный с помощью PrefabUtility.InstantiatePrefab? - PullRequest
0 голосов
/ 15 января 2019

Обычно вы создаете экземпляр сценария для клона префаба, используя

var obj = (GameObject)Instantiate(....);

и чем изменить его родительский с помощью

var obj.transform.SetParent(...);

Однако я пишу небольшой скрипт-редактор для создания префабов над пунктами меню, в которых должна быть ссылка на префаб. Я делаю это в static классе, как:

public static class EditorMenu
{
    // This is a reference that I already have and is not null
    privtae static Transform exampleParent;

    [MenuItem("Example/Create Clone")]
    private static void CreateClone()
    {
        var prefab = AssetDatabase.LoadAssetAtPath("Example/Path/myObject.prefab", typeof(GameObject));
        var obj = (GameObject)PrefabUtility.InstantiatePrefab(prefab);

        obj.transform.position = Vector3.zero;
        obj.transform.rotation = Quaternion.identity;

        Selection.activeGameObject = obj;
    }
}

Я должен был использовать

(GameObject)PrefabUtility.InstantiatePrefab(prefab);

потому что Instantiate() не сохраняет ссылку на префаб, а создает клон.

Итак, приведенный выше код отлично работает, и объект вставляется в сцену, как если бы я перетаскивал его.

Теперь я бы хотел изменить родительский объект для новых экземпляров на parent, поэтому я добавил строку

obj.transform.SetParent(exampleParent, true);

я тоже пробовал

obj.transform.parent = exampleParent;

Но оба выдают исключение:

Установка родительского элемента преобразования, находящегося в префабе, отключена для предотвращения повреждения данных. UnityEngine.Transform: SetParent (Transform)

prefab и, следовательно, obj являются верхними GameObject префаба, поэтому я подумал, что устанавливаю родителя для всего экземпляра объекта, а не какого-либо преобразования внутри иерархии префабов.

Как мне изменить родителя GameObject, созданного с помощью PrefabUtility.InstantiatePrefab?


Обновление

Обходной путь, который я только что попробовал, состоял в том, чтобы фактически использовать Instantiate и сделать

var obj = Object.Instantiate(prefab, cancel.transform);

// remove the added "(clone)" suffix
obj.name = prefab.name;
obj.transform.SetParent(cancel.transform);

однако, как уже упоминалось ранее, это не полностью сохраняет функциональность prefb без изменений ... поэтому позволяет только Revert, но , а не до Apply. Как обходной путь, он может быть достаточно хорошим, так как в моем случае я использую его как ярлык для создания префаба, который пользователи не должны менять позже ...

Ответы [ 2 ]

0 голосов
/ 15 января 2019

Извините, я только что нашел проблему:

Я не добавил его, поскольку сообщение об ошибке сбивало с толку / неправильно сформулировано.

Я использовал Resources.FindObjectsOfTypeAll для проверки, был ли exampleParent типа SomeType на сцене.

Следуя примеру Unity, который должен исключить префабы, которые я использовал

// Validation for the Menu item
[MenuItem("Example/Create Clone", true]
private bool TargetAvailable()
{
    foreach (var target in (SomeType[])Resources.FindObjectsOfTypeAll(typeof(SomeType))
    { 
        if (target.hideFlags == HideFlags.NotEditable || target.hideFlags == HideFlags.HideAndDontSave)
            continue;

        if (!EditorUtility.IsPersistent(target.transform.root.gameObject))
            continue;

        exampleParent = target.transform;
        return true;
    }

    exampleParent = null;
    return false;
}

Но это, похоже, на самом деле неправильно и не работает, так как оно всегда возвращало мне ссылку SomeType из префабов! (Я уже нашел немного странным, что они делают

!EditorUtility.IsPersistent(target.transform.root.gameObject))
    continue;

Я не уверен, если это !, может быть, это тип в их примере кода?!


Так что ошибка, которая звучит так, как если бы родитель был запрещён, на самом деле означает и должна сказать

установка родительского элемента на a Преобразование, которое находится в префабе, не допускается ...

чем я бы вообще нашел актуальную проблему.


Итак, снова в качестве обходного пути, пока я не смогу выяснить, что FindObjectsOfTypeAll вещь, которую я переключил на Object.FindObjectOfType вместо этого, предполагая, что моя цель всегда будет активной на сцене. И использование SetParent теперь работает вместе с PrefabUtitlity.InstantiatePrefab.

0 голосов
/ 15 января 2019

Как изменить родителя объекта GameObject, созданного с помощью PrefabUtility.InstantiatePrefab?

Это правильно, но убедитесь, что cancel также является экземпляром объекта.

obj.transform.parent = cancel.transform;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...