通常您会在脚本中使用
实例化预制件的克隆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;
但是两者都抛出异常:
Setting the parent of a transform which resides in a prefab is disabled to prevent data corruption. UnityEngine.Transform:SetParent(Transform)
prefab
因此 obj
是预制件的最顶层 GameObject
所以我想我设置的是整个实例化对象的父级而不是任何在预制件层次结构内部进行转换。
如何更改通过 PrefabUtility.InstantiatePrefab
实例化的 GameObject
的父级?
更新
我刚刚尝试的解决方法是实际使用 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
变化。作为解决方法,它可能已经足够好了,但是因为在我的例子中,我将它用作实例化预制件的快捷方式,用户以后不应该真正更改......
最佳答案
抱歉,我刚刚发现问题:
我没有添加它,因为错误消息令人困惑/表述不当。
我正在使用 Resources.FindObjectsOfTypeAll
用于检查 SomeType
类型的 exampleParent
是否在场景中。
按照 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;
我不确定 !
是否是他们示例代码中的类型?!
所以听起来像不允许设置父级的错误实际上意味着并且应该说
setting the parent to a Transform which resides in a prefab is not allowed ...
我一开始就发现了实际问题。
所以再次作为解决方法,直到我弄清楚 FindObjectsOfTypeAll
的事情我切换到 Object.FindObjectOfType
而不是假设我的目标将始终在场景中处于事件状态。使用 SetParent
现在可以与 PrefabUtitlity.InstantiatePrefab
一起使用。
关于c# - 如何更改通过 PrefabUtility.InstantiatePrefab 实例化的 GameObject 的父对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54202072/