【问题标题】:When trying to build the game I'm getting error/s in the editor console but not in the visual studio. How can I fix it?尝试构建游戏时,我在编辑器控制台中遇到错误,但在视觉工作室中却没有。我该如何解决?
【发布时间】:2020-02-22 23:52:35
【问题描述】:

在我使用 SceneManagement 的脚本中:

using UnityEditor.SceneManagement;

但它是灰色的,就像我没有在脚本中使用它一样。但是,如果我将删除该行:

using UnityEditor.SceneManagement;

它不会在 Visual Studio 中显示错误,但如果我现在尝试在编辑器中编译游戏,它将在需要 SceneManagement 的地方的控制台中显示 10 个错误。

此脚本之前从未出现过错误。它是在我尝试构建游戏时开始的。

我的部分脚本的屏幕截图。 SceneManagement 是灰色的,好像不需要或正在使用,但它是:

以及编辑器中的建筑设置窗口:

我试图关闭退出 Visual Studio 并在编辑器中双击脚本重新打开它,但它没有改变任何东西。

完整的脚本:

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

public class ObjectsReplace : MonoBehaviour
{
    public GameObject prefabToInit;
    public bool deleteAllShaders = false;

    private const string c_doorRight = "Door_Right";
    private const string c_doorLeft = "Door_Left";
    private const string c_doorShieldFxLocked = "DoorShieldFXLocked";

    public List<GameObject> FindDoors(string[] SpecificParents)
    {
        GameObject[] doorsLeft = GameObject.FindGameObjectsWithTag(c_doorLeft);
        GameObject[] doorsRight = GameObject.FindGameObjectsWithTag(c_doorRight);

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

        if (deleteAllShaders == false)
        {
            List<GameObject> toRemove = new List<GameObject>();
            for (int i = 0; i < allDoors.Count; i++)
            {
                bool match = true;
                for (int x = 0; x < SpecificParents.Length; x++)
                {
                    match &= allDoors[i].transform.parent.name != SpecificParents[x];
                }
                if (match)
                {
                    toRemove.Add(allDoors[i]);
                }
            }
            foreach (var it in toRemove)
            {
                allDoors.Remove(it);
            }
        }

        return allDoors;
    }

    public void DeleteAllShaders()
    {
        if(deleteAllShaders == true)
        {
            UpdateOrAddShaderPrefabToDoors();
        }
    }

    public void UpdateOrAddShaderPrefabToDoors()
    {
        var allDoors = FindDoors(new string[]{ "Wall_Door_Long_01", "Wall_Door_Long_02", "Wall_Interior_Door_02" });

        HashSet<GameObject> prefabParentsOfDoorsNeedRemove = new HashSet<GameObject>();
        allDoors.ForEach(doorGameObject =>
        {
            List<GameObject> shadersChildren = new List<GameObject>();
            for (int i=0; i<doorGameObject.transform.childCount ;i++)
            {
                if (doorGameObject.transform.GetChild(i).name.StartsWith(c_doorShieldFxLocked))
                {
                    shadersChildren.Add(doorGameObject.transform.GetChild(i).gameObject);
                }
            }
            foreach (GameObject shader in shadersChildren)
            {
                GameObject outermostPrefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(shader);
                prefabParentsOfDoorsNeedRemove.Add(outermostPrefabInstanceRoot);
            }
        });

        foreach (GameObject parent in prefabParentsOfDoorsNeedRemove)
        {
            Modify(parent, RemoveFunc);
        }

        HashSet<GameObject> prefabParentsOfDoors = new HashSet<GameObject>();
        allDoors.ForEach(doorGameObject =>
        {
            GameObject outermostPrefabInstanceRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(doorGameObject);
            prefabParentsOfDoors.Add(outermostPrefabInstanceRoot);
        });

        if (deleteAllShaders == false)
        {
            foreach (GameObject parent in prefabParentsOfDoors)
            {
                AddShaderToPrefab(parent);
            }
        }
    }

    private void AddShaderToPrefab(GameObject child)
    {
        Modify(child, AddShaderToAllDoorsFunc);
    }

    private GameObject AddShaderToAllDoorsFunc(GameObject prefab)
    {
        var children = prefab.GetComponentsInChildren<Transform>();

        //Debug.Log($"Total child count before:{children.Count()}");
        int doorsFound = 0;
        foreach (Transform trans in children)
        {
            if (trans.name == c_doorLeft || (trans.name == c_doorRight))
            {
                //Debug.Log("Found door, adding");
                GameObject shader = GetDoorShaderPrefab();

                // clone prefab and attach to parent
                Instantiate(shader, trans); 
                doorsFound++;
            }
        }

        children = prefab.GetComponentsInChildren<Transform>();
        //Debug.Log($"Total child count after:{children.Count()}, doors found:{doorsFound}");

        return prefab;
    }

    private GameObject GetDoorShaderPrefab()
    {
        string[] shieldPrefab = AssetDatabase.FindAssets(c_doorShieldFxLocked);
        //Debug.Assert(shieldPrefab.Length == 1, "Expected exactly 1 shield like this...");
        string shieldGuid = shieldPrefab[0];
        string prefabPath = AssetDatabase.GUIDToAssetPath(shieldGuid);
        GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
        //Debug.Assert(prefab != null, "Expected prefab to load");
        return prefab;
    }

    private GameObject RemoveFunc(GameObject prefab)
    {
        var children = prefab.GetComponentsInChildren<Transform>();

        //Debug.Log($"child count:{children.Count()}");
        foreach (Transform trans in children)
        {
            if (trans.name.StartsWith(c_doorShieldFxLocked))
            {
                //Debug.Log("Found door shader");
                DestroyImmediate(trans.gameObject);
            }
        }

        children = prefab.GetComponentsInChildren<Transform>();
        //Debug.Log($"child count:{children.Count()}");

        return prefab;
    }

    private void Modify(GameObject parentPrefab, Func<GameObject,GameObject> modifyActionOnPrefab)
    {
        // Get the Prefab Asset root GameObject and its asset path.
        string assetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(parentPrefab);

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

        //PrefabUtility.UnpackPrefabInstance(mostPrefabInstanceRoot, PrefabUnpackMode.Completely, UnityEditor.InteractionMode.AutomatedAction);

        prefab = modifyActionOnPrefab(prefab);

        PrefabUtility.SaveAsPrefabAsset(prefab, assetPath);
        PrefabUtility.UnloadPrefabContents(prefab);
    }
}

这也是我在单声道脚本中使用的编辑器脚本:

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

[CustomEditor(typeof(ObjectsReplace))]
public class ObjectsReplaceEditor : Editor
{
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        ObjectsReplace myScript = (ObjectsReplace)target;

        if (GUILayout.Button("Add"))
        {
            myScript.UpdateOrAddShaderPrefabToDoors();
        }

        GUILayout.Space(20);

        if(GUILayout.Button("Delete all shaders"))
        {
            myScript.DeleteAllShaders();
        }
    }
}

再次!发生了什么:

  1. 我可以在编辑器中运行游戏,没有任何问题。没有错误就没有问题。

  2. 我可以在visual studio中编译和保存脚本没有任何问题没有错误没有问题。

  3. 我不能只在编辑器中构建游戏!!!构建游戏时,它仅在统一编辑器控制台中显示错误!视觉工作室中仍然没有错误。我可以在编辑器中玩游戏 我无法构建游戏。

  4. 使用 UnityEngine 或 UnityEditor 的脚本中存在命名空间 SceneManagement,但这不是问题。问题是无论我将 UnityEngine 或 UnityEditor 与 SceneManagement 一起使用,SceneManagement 都是灰色的,就像没有使用一样,但它正在使用中!

  5. 如果我删除删除单声道和编辑器的脚本,我可以构建游戏!

  6. 我还不明白为什么在构建它时在构建设置中给我这个错误,但它们没有在视觉工作室中显示!

【问题讨论】:

  • 当您有特定于平台的定义时,可能会发生这种情况。 ObjectsReplace.cs 的其余部分是什么样的?
  • @Iggy 我刚刚编辑了我的问题添加了完整的脚本。但是为什么它没有在 visua lstudio 中显示错误,而只在编辑器中显示?
  • 也许问题是我现在使用的是统一版本 2019.3.2f1 个人而不是 2019.2.5f1 个人?也许它改变了一些东西?几个小时前我更新了我的统一,它确实为脚本导入了。

标签: c# unity3d


【解决方案1】:

使用UnityEngine.SceneManagement,而不是UnityEditor.SceneManagement

【讨论】:

  • 我会,但这并不能解释为什么我在 Visual Studio 中看不到任何错误,当我在 Visual Studio 中构建时,一切都很好,没有错误。但是在我构建游戏时在编辑器中显示错误。
  • @DanielLip 您不能在要在构建中使用的脚本中使用 UnityEditor 命名空间,因为未使用它编译相应的 DLL。当您需要使用 UnityEditor 命名空间时,请确保脚本位于 Editor 文件夹中。
  • @Iggy 这不是问题!问题是在视觉工作室中它没有显示任何错误!在统一编辑器中,我可以运行我的游戏,一切都很好。只有当我尝试构建游戏时,它才会在统一编辑器中显示错误,而不是在视觉工作室中。
  • 编辑器脚本在编辑器文件夹中,如果我使用 UnityEngine.SceneManagement 则尝试构建它只在编辑器中提供给我的游戏!!!!单声道脚本中的 10 个新错误需要与 UnityEditor.SceneManagement 而非引擎一起使用!!!使用 UnityEngine 时,使用 UnityEditor.SceneManagement 时出现 10 个错误
  • 我从来没有遇到过这两个脚本的错误或问题。几个小时前就开始了。为什么它只在统一编辑器中显示错误,并且只在构建游戏时显示?如果有错误为什么我可以在编辑器中玩游戏?
【解决方案2】:

我知道您可能已经找到了解决方案,但要向其他人澄清一下:问题在于您使用的是命名空间 UnityEditor

UnityEditor 仅在编辑器中运行项目时可用。您将不得不找到另一种保存预制件的方法。您可以将所需的信息保存在PlayerPrefs 中,并摆脱UnityEditor 命名空间。使用UnityEngine.SceneManagement 而不是UnityEditor.SceneManagement

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-09
    • 2019-06-24
    • 2021-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 1970-01-01
    相关资源
    最近更新 更多