【问题标题】:Why I'm getting empty string when trying to get a prefab asset path?为什么我在尝试获取预制资产路径时得到空字符串?
【发布时间】:2020-02-16 05:32:59
【问题描述】:
 private void ModifyPrefab(GameObject child)
    {
        var mostPrefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(child);

        // Get the Prefab Asset root GameObject and its asset path.
        string assetPath = AssetDatabase.GetAssetPath(mostPrefabInstanceRoot);

        // Load the contents of the Prefab Asset.
        GameObject contentsRoot = PrefabUtility.LoadPrefabContents(assetPath);

        // Modify Prefab contents.
        DestroyImmediate(child);

        // Save contents back to Prefab Asset and unload contents.
        PrefabUtility.SaveAsPrefabAsset(contentsRoot, assetPath);
        PrefabUtility.UnloadPrefabContents(contentsRoot);
    }

assetPath 为空“”

运行时第一个 mostPrefabInstanceRoot 是:“Room_Large_Windows_Part_03 (UnityEngine.GameObject)”

在编辑器中这个对象是一个预制件:

然后在预制件上右键单击并选择预制件资产时,它会到达:

但在脚本中字符串返回“”

我不明白为什么它返回空字符串?

现在编辑这是我完成的脚本:

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

public class ObjectsReplace : MonoBehaviour
{
    public GameObject prefabToInit;

    // Note your method should probably return something
    public void UpdateOrAddShaderPrefabToDoors()
    {
        GameObject[] doorsLeft = GameObject.FindGameObjectsWithTag("Door_Left");
        GameObject[] doorsRight = GameObject.FindGameObjectsWithTag("Door_Right");

        List<GameObject> allDoors = doorsLeft.Union(doorsRight).ToList();

        allDoors.ForEach(gameObject =>
        {
            Transform childTransform = gameObject.transform.Find("DoorShieldFXLocked Variant");
            GameObject child = childTransform?.gameObject;
            Debug.Log($"Child exist: {child != null}, Name of child: {child?.name}");
            if (child != null)
            {
                ModifyPrefab(child);
            }
        });
    }

    private void ModifyPrefab(GameObject child)
    {
        var mostPrefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(child);

        // Get the Prefab Asset root GameObject and its asset path.
        string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(mostPrefabInstanceRoot);

        // Load the contents of the Prefab Asset.
        GameObject contentsRoot = PrefabUtility.LoadPrefabContents(assetPath);

        // Modify Prefab contents.
        DestroyImmediate(child);

        // Save contents back to Prefab Asset and unload contents.
        PrefabUtility.SaveAsPrefabAsset(contentsRoot, assetPath);
        PrefabUtility.UnloadPrefabContents(mostPrefabInstanceRoot);
    }
}

但在尝试销毁孩子时仍然在编辑器中出现异常:

InvalidOperationException:不允许在 Prefab 实例中销毁 GameObject。

这个想法是打开它所属的子预制件以销毁子代,然后保存并关闭预制件,就像在编辑器中但从脚本中执行 Overrides > Apply Changes 一样。

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    看起来mostPrefabInstanceRoot 不是资产,这是有道理的,因为它是预制件的一个实例。使用PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot 而不是AssetDatabase.GetAssetPath

    string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(mostPrefabInstanceRoot);
    

    另外,为了使您的编辑生效,您可能希望保存 mostPrefabInstanceRoot 而不是 contentRoot,因为删除子项后 contentRoot 将保持不变。

    【讨论】:

    • 我在编辑器中遇到异常:InvalidOperationException: Destroying a GameObject inside a Prefab instance is not allowed.
    • 我编辑了我的问题,添加了我完成的脚本和我正在尝试做的事情。
    猜你喜欢
    • 2017-11-22
    • 1970-01-01
    • 2011-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多